From 2f4139e5d313902683a3a4a98f9ef012afff8734 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 7 Oct 2014 12:30:54 +0200 Subject: [PATCH 001/200] Initial commit --- autotest.pro | 6 + plugins/autotest/AutoTest.json.in | 15 + plugins/autotest/autotest.pro | 33 +++ plugins/autotest/autotest.qrc | 9 + plugins/autotest/autotest_dependencies.pri | 12 + plugins/autotest/autotest_global.h | 31 ++ plugins/autotest/autotestconstants.h | 34 +++ plugins/autotest/autotestplugin.cpp | 102 +++++++ plugins/autotest/autotestplugin.h | 50 ++++ plugins/autotest/images/class.png | Bin 0 -> 573 bytes plugins/autotest/images/collapse.png | Bin 0 -> 205 bytes plugins/autotest/images/expand.png | Bin 0 -> 216 bytes plugins/autotest/images/func.png | Bin 0 -> 709 bytes plugins/autotest/images/sort.png | Bin 0 -> 233 bytes plugins/autotest/testcodeparser.cpp | 261 ++++++++++++++++ plugins/autotest/testcodeparser.h | 63 ++++ plugins/autotest/testinfo.cpp | 34 +++ plugins/autotest/testinfo.h | 52 ++++ plugins/autotest/testtreeitem.cpp | 136 +++++++++ plugins/autotest/testtreeitem.h | 76 +++++ plugins/autotest/testtreemodel.cpp | 329 +++++++++++++++++++++ plugins/autotest/testtreemodel.h | 80 +++++ plugins/autotest/testtreeview.cpp | 204 +++++++++++++ plugins/autotest/testtreeview.h | 94 ++++++ plugins/autotest/testvisitor.cpp | 75 +++++ plugins/autotest/testvisitor.h | 54 ++++ qtcreatorplugin.pri | 8 + shared/autotest/auto.pro | 3 + shared/autotest/autotest_24.png | Bin 0 -> 683 bytes shared/autotest/main.cpp | 18 ++ shared/autotest/src.pro | 10 + shared/autotest/tests.pro | 3 + shared/autotest/tmp.pro | 12 + shared/autotest/tst.pro | 14 + shared/autotest/tst_src.cpp | 58 ++++ shared/autotest/wizard.xml | 92 ++++++ shared/shared.pro | 10 + 37 files changed, 1978 insertions(+) create mode 100644 autotest.pro create mode 100644 plugins/autotest/AutoTest.json.in create mode 100644 plugins/autotest/autotest.pro create mode 100644 plugins/autotest/autotest.qrc create mode 100644 plugins/autotest/autotest_dependencies.pri create mode 100644 plugins/autotest/autotest_global.h create mode 100644 plugins/autotest/autotestconstants.h create mode 100644 plugins/autotest/autotestplugin.cpp create mode 100644 plugins/autotest/autotestplugin.h create mode 100644 plugins/autotest/images/class.png create mode 100644 plugins/autotest/images/collapse.png create mode 100644 plugins/autotest/images/expand.png create mode 100644 plugins/autotest/images/func.png create mode 100644 plugins/autotest/images/sort.png create mode 100644 plugins/autotest/testcodeparser.cpp create mode 100644 plugins/autotest/testcodeparser.h create mode 100644 plugins/autotest/testinfo.cpp create mode 100644 plugins/autotest/testinfo.h create mode 100644 plugins/autotest/testtreeitem.cpp create mode 100644 plugins/autotest/testtreeitem.h create mode 100644 plugins/autotest/testtreemodel.cpp create mode 100644 plugins/autotest/testtreemodel.h create mode 100644 plugins/autotest/testtreeview.cpp create mode 100644 plugins/autotest/testtreeview.h create mode 100644 plugins/autotest/testvisitor.cpp create mode 100644 plugins/autotest/testvisitor.h create mode 100644 qtcreatorplugin.pri create mode 100644 shared/autotest/auto.pro create mode 100644 shared/autotest/autotest_24.png create mode 100644 shared/autotest/main.cpp create mode 100644 shared/autotest/src.pro create mode 100644 shared/autotest/tests.pro create mode 100644 shared/autotest/tmp.pro create mode 100644 shared/autotest/tst.pro create mode 100644 shared/autotest/tst_src.cpp create mode 100644 shared/autotest/wizard.xml create mode 100644 shared/shared.pro diff --git a/autotest.pro b/autotest.pro new file mode 100644 index 00000000000..77543b34a51 --- /dev/null +++ b/autotest.pro @@ -0,0 +1,6 @@ +TEMPLATE = subdirs +CONFIG += ordered + +SUBDIRS += plugins/autotest shared + +QMAKE_EXTRA_TARGETS = docs install_docs # dummy targets for consistency diff --git a/plugins/autotest/AutoTest.json.in b/plugins/autotest/AutoTest.json.in new file mode 100644 index 00000000000..dd25f250d26 --- /dev/null +++ b/plugins/autotest/AutoTest.json.in @@ -0,0 +1,15 @@ +{ +\"Name\" : \"AutoTest\", +\"Version\" : \"$$QTCREATOR_VERSION\", +\"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\", +\"Experimental\" : true, +\"Vendor\" : \"Digia Plc\", +\"Copyright\" : \"(C) 2014 Digia Plc\", +\"License\" : [ \"Commercial Usage\", +\"\", +\"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Digia.\" +], +\"Description\" : \"Auto Test plugin.\", +\"Url\" : \"http://qt.digia.com\", +$$dependencyList +} diff --git a/plugins/autotest/autotest.pro b/plugins/autotest/autotest.pro new file mode 100644 index 00000000000..19df6bcb2eb --- /dev/null +++ b/plugins/autotest/autotest.pro @@ -0,0 +1,33 @@ +TARGET = AutoTest +TEMPLATE = lib + +PROVIDER = Digia + +include(../../qtcreatorplugin.pri) +include(autotest_dependencies.pri) + +DEFINES += AUTOTEST_LIBRARY + +SOURCES += \ + testtreeview.cpp \ + testtreemodel.cpp \ + testtreeitem.cpp \ + testvisitor.cpp \ + testinfo.cpp \ + testcodeparser.cpp \ + autotestplugin.cpp + +HEADERS += \ + testtreeview.h \ + testtreemodel.h \ + testtreeitem.h \ + testvisitor.h \ + testinfo.h \ + testcodeparser.h \ + autotestplugin.h \ + autotest_global.h \ + autotestconstants.h + +RESOURCES += \ + autotest.qrc + diff --git a/plugins/autotest/autotest.qrc b/plugins/autotest/autotest.qrc new file mode 100644 index 00000000000..53dee42e310 --- /dev/null +++ b/plugins/autotest/autotest.qrc @@ -0,0 +1,9 @@ + + + images/class.png + images/func.png + images/expand.png + images/collapse.png + images/sort.png + + diff --git a/plugins/autotest/autotest_dependencies.pri b/plugins/autotest/autotest_dependencies.pri new file mode 100644 index 00000000000..af150efd0c4 --- /dev/null +++ b/plugins/autotest/autotest_dependencies.pri @@ -0,0 +1,12 @@ +QTC_PLUGIN_NAME = AutoTest + +QTC_PLUGIN_DEPENDS += \ + coreplugin \ + projectexplorer \ + cpptools + +QTC_LIB_DEPENDS += \ + cplusplus \ + utils + +#QTC_PLUGIN_RECOMMENDS += \ diff --git a/plugins/autotest/autotest_global.h b/plugins/autotest/autotest_global.h new file mode 100644 index 00000000000..3f3c6ae192a --- /dev/null +++ b/plugins/autotest/autotest_global.h @@ -0,0 +1,31 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef AUTOTEST_GLOBAL_H +#define AUTOTEST_GLOBAL_H + +#include + +#if defined(AUTOTEST_LIBRARY) +# define AUTOTESTSHARED_EXPORT Q_DECL_EXPORT +#else +# define AUTOTESTSHARED_EXPORT Q_DECL_IMPORT +#endif + +#endif // AUTOTEST_GLOBAL_H + diff --git a/plugins/autotest/autotestconstants.h b/plugins/autotest/autotestconstants.h new file mode 100644 index 00000000000..df3e26be11b --- /dev/null +++ b/plugins/autotest/autotestconstants.h @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef AUTOTESTCONSTANTS_H +#define AUTOTESTCONSTANTS_H + +namespace Autotest { +namespace Constants { + +const char ACTION_ID[] = "AutoTest.Action"; +const char MENU_ID[] = "AutoTest.Menu"; +const char AUTOTEST_ID[] = "AutoTest.ATP"; +const char AUTOTEST_CONTEXT[] = "Auto Tests"; + +} // namespace Autotest +} // namespace Constants + +#endif // AUTOTESTCONSTANTS_H + diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp new file mode 100644 index 00000000000..b0da2c1cac8 --- /dev/null +++ b/plugins/autotest/autotestplugin.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "autotestplugin.h" +#include "autotestconstants.h" +#include "testtreeview.h" +#include "testtreemodel.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +using namespace Autotest::Internal; + +AutotestPlugin::AutotestPlugin() +{ + // Create your members +} + +AutotestPlugin::~AutotestPlugin() +{ + // Unregister objects from the plugin manager's object pool + // Delete members + TestTreeModel *model = TestTreeModel::instance(); + delete model; +} + +bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorString) +{ + // Register objects in the plugin manager's object pool + // Load settings + // Add actions to menus + // Connect to other plugins' signals + // In the initialize function, a plugin can be sure that the plugins it + // depends on have initialized their members. + + Q_UNUSED(arguments) + Q_UNUSED(errorString) + + QAction *action = new QAction(tr("Autotest action"), this); + Core::Command *cmd = Core::ActionManager::registerAction(action, Constants::ACTION_ID, + Core::Context(Core::Constants::C_GLOBAL)); + cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Meta+A"))); + connect(action, SIGNAL(triggered()), this, SLOT(triggerAction())); + + Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::MENU_ID); + menu->menu()->setTitle(tr("Tests")); + menu->addAction(cmd); + Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu); + + addAutoReleasedObject(new TestViewFactory); + + return true; +} + +void AutotestPlugin::extensionsInitialized() +{ + // Retrieve objects from the plugin manager's object pool + // In the extensionsInitialized function, a plugin can be sure that all + // plugins that depend on it are completely initialized. +} + +ExtensionSystem::IPlugin::ShutdownFlag AutotestPlugin::aboutToShutdown() +{ + // Save settings + // Disconnect from signals that are not needed during shutdown + // Hide UI (if you add UI that is not in the main window directly) + return SynchronousShutdown; +} + +void AutotestPlugin::triggerAction() +{ + QMessageBox::information(Core::ICore::mainWindow(), + tr("Action triggered"), + tr("This is an action from Autotest.")); +} + diff --git a/plugins/autotest/autotestplugin.h b/plugins/autotest/autotestplugin.h new file mode 100644 index 00000000000..6391f050feb --- /dev/null +++ b/plugins/autotest/autotestplugin.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef AUTOTESTPLUGIN_H +#define AUTOTESTPLUGIN_H + +#include "autotest_global.h" + +#include + +namespace Autotest { +namespace Internal { + +class AutotestPlugin : public ExtensionSystem::IPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "AutoTest.json") + +public: + AutotestPlugin(); + ~AutotestPlugin(); + + bool initialize(const QStringList &arguments, QString *errorString); + void extensionsInitialized(); + ShutdownFlag aboutToShutdown(); + +private slots: + void triggerAction(); +}; + +} // namespace Internal +} // namespace Autotest + +#endif // AUTOTESTPLUGIN_H + diff --git a/plugins/autotest/images/class.png b/plugins/autotest/images/class.png new file mode 100644 index 0000000000000000000000000000000000000000..88432d2cb10c43de91fdb7ec7989285090747b0a GIT binary patch literal 573 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7BuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztFy8lcaSW-rHD&U7Z)r!7A7c1La z{;|7iR0MxnBB1-_-NG+Rn%d*M_`hbX5?}g{q1WDV;;+^0j)n^ymn@CY`k`znSZ2PF z<#AvBvAYx2*mv;D8SnmVXMF$rJswWQfSmWYPCR&c=kFTnSt6b`sYT4^cSj{|uztCD zzEbHfy(cmMwEI5perEsk^8vNc>w6l?_O{-e#~-rfnd9a6hqssxmG-TrmX1VLRDt@-S;0n$p|^fJTZA|z#Y43>k17uZ1?uQiQv)x zHm&QWc>N@m=!e%7A0C^2KquaVHSb@m1m|j*J>4qWy6)=}{_)zV#?OkA4iBBWJWl+> z71fDyJZ!Dz?!~(gzB?oLPwaht4wvQiz&20OpIm%v>pOS)*G8D|N| zl}uaa;eCe=9aXL4~&vMP;?~fH37#J8lUHx3vIVCg!04d1;cmMzZ literal 0 HcmV?d00001 diff --git a/plugins/autotest/images/collapse.png b/plugins/autotest/images/collapse.png new file mode 100644 index 0000000000000000000000000000000000000000..d6da22a5b86804591b12af7205efb0c2d5b08ea6 GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0y~yVBiE{4mJh`h6fYb1Q-|?7>k44ofy`glX=O&z`&N| z?e4a1@p0td-tRLqan6F$jH88rfulD!<|Ns9>7CgMYJ^z1tk^+;!(hk;RJBpw4 zwe1cG36YSLkdP?YrKw~z%fwvpskK|uAx?&<(1g(0E&Wvt3=9mOu6{1-oD!Mk44ofy`glX=O&z`&N| z?e4z?Djv}DuUP*w&{ zuY3lBz4~|O?p(t^Ek%K=A#K^adtbQh?mE6m`oGjWzH8a#6Z7?YimdIQtZ3|IU|?YI MboFyt=akR{0Hk44ofy`glX=O&z`&N| z?e4;Gn!%AF|Mcab-3$y2oCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`wcE$ZevrGce`>J z7#Ji=Tq8=H^K)}k^GX<;i&7IyQd1PlGfOfQ+&z5*!W;R-85o!pJY5_^EKV<-d_G&) zQRMjk**S~4FE&hc6EtgAStM~pgk`FLpbZPtQCE(pjKEdxaYwo<4B9t!i~Mhjv+4Zb z^y1=$W6e4Kg3@n=Zko6yCDpxo^G0m5b=;Xvv%gp@M(kh~UKdD8Aq z<*8{->g@ki8u#D1Gxv>rv}xYcgU%ewg?9wa>1M0E7c6wcx9nY5r>0YzuSiUE#DQz8 zO?#w#=Xfny)R<6EysA^KX0yorx!MKGt{vL!o+|R0^~?V9#G7I|vzunH^nMd7ojLp2 z-wix#*}0ETd7jYu*O2EGZ_K>2iHqY7FBSJskYdSyufO)i`kbts66{Hs+Z9)?;8W+R|q%w_NLWwp+bLgD0nk zspE>q_04i`TW|J#cG9$c&YF@Td%Q5{z5VrGK|=?frgH@jlF6C&OI}-Te;q$zVQI{9 z&#k}j_q@ySxXEYwKQs7JO2%B(=a&`jWjb9}P2Qo=mGj75Y2qvYq6cC(MT~w)F)%PN Nc)I$ztaD0e0sw>aEhhi~ literal 0 HcmV?d00001 diff --git a/plugins/autotest/images/sort.png b/plugins/autotest/images/sort.png new file mode 100644 index 0000000000000000000000000000000000000000..2718b01d6e242bc15a086de14bb00b59bcee41f0 GIT binary patch literal 233 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s77>k44ofy`glX=O&z`&N| z?e4E_KoGVBLf3N zrl*Tzh{frnfsR}a20Y&G`zJMrAN;@nfcO)`&nhQwEGcE?-aBQPr&L0!=c>pacK-Ja zehdnknXKn4cR$|z&Fc$;=j)T_HEuA-oDSC5eDU{mcD}_u5gFw! gi{hW=_*YCjmbonpiSprRU|?YIboFyt=akR{0E+idod5s; literal 0 HcmV?d00001 diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp new file mode 100644 index 00000000000..dbee199976f --- /dev/null +++ b/plugins/autotest/testcodeparser.cpp @@ -0,0 +1,261 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "testcodeparser.h" +#include "testinfo.h" +#include "testtreeitem.h" +#include "testtreemodel.h" +#include "testvisitor.h" + +#include +#include + +#include +#include + +#include + +namespace Autotest { +namespace Internal { + +TestCodeParser::TestCodeParser(TestTreeModel *parent) + : QObject(parent), + m_model(parent), + m_currentProject(0) +{ +} + +void TestCodeParser::updateTestTree() +{ + qDebug("updating TestTreeModel"); + m_model->beginResetModel(); + qDeleteAll(m_cppDocMap); + m_cppDocMap.clear(); + QModelIndex autoTestRootIndex = m_model->index(0, 0); + TestTreeItem *autoTestRootItem = static_cast(autoTestRootIndex.internalPointer()); + autoTestRootItem->removeChildren(); + m_model->endResetModel(); + ProjectExplorer::SessionManager *session = static_cast( + ProjectExplorer::SessionManager::instance()); + if (!session || !session->hasProjects()) + return; + + m_currentProject = session->startupProject(); + if (!m_currentProject) + return; + scanForTests(); +} + +/****** scan for QTest related stuff helpers ******/ + +static bool includesQtTest(const CPlusPlus::Document::Ptr &doc, + const CppTools::CppModelManager *cppMM) +{ + QList includes = doc->resolvedIncludes(); + + foreach (CPlusPlus::Document::Include inc, includes) { + // TODO this short cut works only for #include + // bad, as there could be much more different approaches + if (inc.unresolvedFileName() == QLatin1String("QtTest") + && inc.resolvedFileName().endsWith(QLatin1String("QtTest/QtTest"))) { + return true; + } + } + + if (cppMM) { + CPlusPlus::Snapshot snapshot = cppMM->snapshot(); + QSet includes = snapshot.allIncludesForDocument(doc->fileName()); + foreach (QString include, includes) { + if (include.endsWith(QLatin1String("QtTest/qtest.h"))) { + return true; + } + } + } + return false; +} + +static bool qtTestLibDefined(const CppTools::CppModelManager *cppMM, + const QString &fileName) +{ + QList parts = cppMM->projectPart(fileName); + if (parts.size() > 0) { + QByteArray projDefines = parts.at(0)->projectDefines; + return projDefines.contains("#define QT_TESTLIB_LIB 1"); + } + return false; +} + +static QString testClass(const CPlusPlus::Document::Ptr &doc) +{ + static QByteArray qtTestMacros[] = {"QTEST_MAIN", "QTEST_APPLESS_MAIN", "QTEST_GUILESS_MAIN"}; + QString tC; + QList macros = doc->macroUses(); + + foreach (CPlusPlus::Document::MacroUse macro, macros) { + if (!macro.isFunctionLike()) + continue; + QByteArray name = macro.macro().name(); + if (name == qtTestMacros[0] || name == qtTestMacros[1] || name == qtTestMacros[2]) { + CPlusPlus::Document::Block arg = macro.arguments().at(0); + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + + // TODO high costs....?! + CppTools::WorkingCopy wc = cppMM->workingCopy(); + if (wc.contains(doc->fileName())) { + QByteArray src = wc.source(doc->fileName()); + tC = QLatin1String(src.mid(arg.bytesBegin(), arg.bytesEnd() - arg.bytesBegin())); + } else { + QFile current(doc->fileName()); + if (current.exists() && current.open(QFile::ReadOnly)) { + CPlusPlus::Document::Block arg = macro.arguments().at(0); + if (current.seek(arg.bytesBegin())) { + QByteArray res = current.read(arg.bytesEnd() - arg.bytesBegin()); + if (!res.isEmpty()) + tC = QLatin1String(res); + } + current.close(); + } + } + break; + } + } + return tC; +} + +/****** end of helpers ******/ + +void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) +{ + const QString file = doc->fileName(); + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + + if (includesQtTest(doc, cppMM) && qtTestLibDefined(cppMM, file)) { + QString tc = testClass(doc); + if (tc.isEmpty()) { + // one might have used an approach without macros or defined own macros + QString src = QLatin1String(doc->utf8Source()); // does not work anymore - src is always "" + if (src.contains(QLatin1String("QTest::qExec"))) { + qDebug() << "Src\n===============\n" << src << "\n=============\n"; + // TODO extract the class name by using the AST - using regex is too problematic as this + // does not take comments and typedefs or whatever into account.... + qDebug() << "Currently not supported approach... (self-defined macro / QTest::qExec() call/...)"; + } + } else { + QModelIndex autoTestRootIndex = m_model->index(0, 0); + TestTreeItem *autoTestRootItem = static_cast(autoTestRootIndex.internalPointer()); + TestTreeItem *ttItem = new TestTreeItem(tc, file, TestTreeItem::TEST_CLASS, + autoTestRootItem); + CPlusPlus::TypeOfExpression toe; + toe.init(doc, cppMM->snapshot()); + CPlusPlus::Document::Ptr declaringDoc = doc; + QList toeItems = toe(tc.toUtf8(), doc->globalNamespace()); + if (toeItems.size()) { + CPlusPlus::Class *toeClass = toeItems.first().declaration()->asClass(); + QString declFileName = QLatin1String(toeClass->fileId()->chars(), + toeClass->fileId()->size()); + declaringDoc = cppMM->snapshot().document(declFileName); + ttItem->setFilePath(declFileName); + ttItem->setLine(toeClass->line()); + ttItem->setColumn(toeClass->column() - 1); + } + if (declaringDoc.isNull()) + return; + TestVisitor myVisitor(tc); + myVisitor.accept(declaringDoc->globalNamespace()); + QMap privSlots = myVisitor.privateSlots(); + foreach (const QString privS, privSlots.keys()) { + TestCodeLocation location = privSlots.value(privS); + TestTreeItem *ttSub = new TestTreeItem(privS, location.m_fileName, + TestTreeItem::TEST_FUNCTION, ttItem); + ttSub->setLine(location.m_line); + ttSub->setColumn(location.m_column); + ttItem->appendChild(ttSub); + } + if (m_cppDocMap.contains(file)) { + TestInfo *info = m_cppDocMap[file]; + int count = autoTestRootItem->childCount(); + for (int i = 0; i < count; ++i) { + TestTreeItem *currentItem = autoTestRootItem->child(i); + if (currentItem->filePath() == file) { + m_model->modifyAutoTestSubtree(i, ttItem); + m_cppDocMap.insert(file, new TestInfo(tc, privSlots.keys(), + doc->revision(), + doc->editorRevision())); + break; + } + } + delete info; + delete ttItem; + } else { + m_model->beginInsertRows(autoTestRootIndex, autoTestRootItem->childCount(), autoTestRootItem->childCount()); + autoTestRootItem->appendChild(ttItem); + m_model->endInsertRows(); + m_cppDocMap.insert(file, new TestInfo(tc, privSlots.keys(), + doc->revision(), doc->editorRevision())); + } + } + } +} + +void TestCodeParser::onDocumentUpdated(CPlusPlus::Document::Ptr doc) +{ + if (!m_currentProject) + return; + QString fileName = doc->fileName(); + if (!m_cppDocMap.contains(fileName)) { + if (!m_currentProject->files(ProjectExplorer::Project::AllFiles).contains(fileName)) { + return; + } + } else { + if (m_cppDocMap[fileName]->revision() == doc->revision() + && m_cppDocMap[fileName]->editorRevision() == doc->editorRevision()) { + qDebug("Skipped due revision equality"); // added to verify if this ever happens.. + return; + } + } + checkDocumentForTestCode(doc); +} + +void TestCodeParser::removeFiles(const QStringList &files) +{ + foreach (QString file, files) { + if (m_cppDocMap.contains(file)) { + TestInfo *info = m_cppDocMap.value(file); + m_cppDocMap.remove(file); + m_model->removeAutoTestSubtreeByFilePath(file); + delete info; + } + } +} + +void TestCodeParser::scanForTests() +{ + QStringList list = m_currentProject->files(ProjectExplorer::Project::AllFiles); + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + CPlusPlus::Snapshot snapshot = cppMM->snapshot(); + + foreach (QString file, list) { + if (snapshot.contains(file)) { + CPlusPlus::Document::Ptr doc = snapshot.find(file).value(); + checkDocumentForTestCode(doc); + } + } +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h new file mode 100644 index 00000000000..0ef4eedc333 --- /dev/null +++ b/plugins/autotest/testcodeparser.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTCODEPARSER_H +#define TESTCODEPARSER_H + +#include + +#include +#include + +namespace ProjectExplorer { +class Project; +} + +namespace Autotest { +namespace Internal { + +class TestInfo; +class TestTreeModel; + +class TestCodeParser : public QObject +{ + Q_OBJECT +public: + explicit TestCodeParser(/*QObject*/TestTreeModel *parent = 0); + +signals: + +public slots: + void updateTestTree(); + void checkDocumentForTestCode(CPlusPlus::Document::Ptr doc); + + void onDocumentUpdated(CPlusPlus::Document::Ptr doc); + void removeFiles(const QStringList &files); + +private: + void scanForTests(); + + TestTreeModel *m_model; + QMap m_cppDocMap; + ProjectExplorer::Project *m_currentProject; +}; + +} // namespace Internal +} // Autotest + +#endif // TESTCODEPARSER_H diff --git a/plugins/autotest/testinfo.cpp b/plugins/autotest/testinfo.cpp new file mode 100644 index 00000000000..8e5850c84be --- /dev/null +++ b/plugins/autotest/testinfo.cpp @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "testinfo.h" + +namespace Autotest { +namespace Internal { + +TestInfo::TestInfo(const QString &className, const QStringList &functions, unsigned revision, + unsigned editorRevision) + : m_className(className), + m_functions(functions), + m_revision(revision), + m_editorRevision(editorRevision) +{ +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testinfo.h b/plugins/autotest/testinfo.h new file mode 100644 index 00000000000..378afcab589 --- /dev/null +++ b/plugins/autotest/testinfo.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTINFO_H +#define TESTINFO_H + +#include + +namespace Autotest { +namespace Internal { + +class TestInfo +{ +public: + explicit TestInfo(const QString &className, const QStringList &functions = QStringList(), + unsigned revision = 0, unsigned editorRevision = 0); + + const QString testClass() const { return m_className; } + void setTestClass(const QString &className) { m_className = className; } + const QStringList testFunctions() const { return m_functions; } + void setTestFunctions(const QStringList &functions) { m_functions = functions; } + unsigned revision() const { return m_revision; } + void setRevision(unsigned revision) { m_revision = revision; } + unsigned editorRevision() const { return m_editorRevision; } + void setEditorRevision(unsigned editorRevision) { m_editorRevision = editorRevision; } + +private: + QString m_className; + QStringList m_functions; + unsigned m_revision; + unsigned m_editorRevision; +}; + +} // namespace Internal +} // namespace Autotest + +#endif // TESTINFO_H diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp new file mode 100644 index 00000000000..7fb8b85e198 --- /dev/null +++ b/plugins/autotest/testtreeitem.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "testtreeitem.h" + +namespace Autotest { +namespace Internal { + +TestTreeItem::TestTreeItem(const QString &name, const QString &filePath, Type type, TestTreeItem *parent) + : m_name(name), + m_filePath(filePath), + m_checked(type == ROOT ? Qt::Unchecked : Qt::Checked), + m_type(type), + m_line(0), + m_parent(parent) +{ +} + +TestTreeItem::~TestTreeItem() +{ + removeChildren(); +} + +TestTreeItem *TestTreeItem::child(int row) +{ + return m_children.at(row); +} + +TestTreeItem *TestTreeItem::parent() const +{ + return m_parent; +} + +void TestTreeItem::appendChild(TestTreeItem *child) +{ + m_children.append(child); +} + +int TestTreeItem::row() const +{ + if (m_parent) + return m_parent->m_children.indexOf(const_cast(this)); + return 0; +} + +int TestTreeItem::childCount() const +{ + return m_children.size(); +} + +void TestTreeItem::removeChildren() +{ + qDeleteAll(m_children); + m_children.clear(); +} + +bool TestTreeItem::removeChild(int row) +{ + if (row < 0 || row >= m_children.size()) + return false; + TestTreeItem *child = m_children.at(row); + m_children.removeAt(row); + delete child; + return true; +} + +bool TestTreeItem::modifyContent(const TestTreeItem *modified) +{ + bool hasBeenModified = false; + if (m_filePath != modified->m_filePath) { + m_filePath = modified->m_filePath; + hasBeenModified = true; + } + if (m_name != modified->m_name) { + m_name = modified->m_name; + hasBeenModified = true; + } + if (m_line != modified->m_line) { + m_line = modified->m_line; + hasBeenModified = true; + } + return hasBeenModified; +} + +void TestTreeItem::setChecked(const Qt::CheckState checkState) +{ + switch (m_type) { + case ROOT: + return; + case TEST_FUNCTION: + m_checked = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked); + m_parent->revalidateCheckState(); + break; + case TEST_CLASS: + Qt::CheckState usedState = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked); + foreach (TestTreeItem *child, m_children) { + child->setChecked(usedState); + } + m_checked = usedState; + } +} + +void TestTreeItem::revalidateCheckState() +{ + if (m_children.size() == 0) + return; + bool foundChecked = false; + bool foundUnchecked = false; + foreach (const TestTreeItem *child, m_children) { + foundChecked |= (child->m_checked != Qt::Unchecked); + foundUnchecked |= (child->m_checked == Qt::Unchecked); + if (foundChecked && foundUnchecked) { + m_checked = Qt::PartiallyChecked; + return; + } + } + m_checked = (foundUnchecked ? Qt::Unchecked : Qt::Checked); +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h new file mode 100644 index 00000000000..edda539fd36 --- /dev/null +++ b/plugins/autotest/testtreeitem.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTTREEITEM_H +#define TESTTREEITEM_H + +#include +#include + +namespace Autotest { +namespace Internal { + +class TestTreeItem +{ + +public: + enum Type { + ROOT, TEST_CLASS, TEST_FUNCTION + }; + + TestTreeItem(const QString &name, const QString &filePath, Type type, TestTreeItem *parent = 0); + virtual ~TestTreeItem(); + + TestTreeItem *child(int row); + TestTreeItem *parent() const; + void appendChild(TestTreeItem *child); + int row() const; + int childCount() const; + void removeChildren(); + bool removeChild(int row); + bool modifyContent(const TestTreeItem *modified); + + const QString name() const { return m_name; } + void setName(const QString &name) { m_name = name; } + const QString filePath() const { return m_filePath; } + void setFilePath(const QString &filePath) { m_filePath = filePath; } + void setLine(unsigned line) { m_line = line;} + unsigned line() const { return m_line; } + void setColumn(unsigned column) { m_column = column; } + unsigned column() const { return m_column; } + void setChecked(const Qt::CheckState checked); + Qt::CheckState checked() const { return m_checked; } + Type type() const { return m_type; } + +private: + void revalidateCheckState(); + + QString m_name; + QString m_filePath; + Qt::CheckState m_checked; + Type m_type; + unsigned m_line; + unsigned m_column; + TestTreeItem *m_parent; + QList m_children; +}; + +} // namespace Internal +} // namespace Autotest + +#endif // TESTTREEITEM_H diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp new file mode 100644 index 00000000000..88bc653d4ec --- /dev/null +++ b/plugins/autotest/testtreemodel.cpp @@ -0,0 +1,329 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "testcodeparser.h" +#include "testtreeitem.h" +#include "testtreemodel.h" + +#include + +#include + +namespace Autotest { +namespace Internal { + +TestTreeModel::TestTreeModel(QObject *parent) : + QAbstractItemModel(parent), + m_rootItem(new TestTreeItem(QString(), QString(), TestTreeItem::ROOT)), + m_autoTestRootItem(new TestTreeItem(tr("Auto Tests"), QString(), TestTreeItem::ROOT, m_rootItem)), +// m_quickTestRootItem(new TestTreeItem(tr("Qt Quick Tests"), QString(), TestTreeItem::ROOT, m_rootItem)), + m_parser(new TestCodeParser(this)) +{ + m_rootItem->appendChild(m_autoTestRootItem); +// m_rootItem->appendChild(m_quickTestRootItem); + m_parser->updateTestTree(); + +// CppTools::CppModelManagerInterface *cppMM = CppTools::CppModelManagerInterface::instance(); +// if (cppMM) { +// // replace later on by +// // cppMM->registerAstProcessor([this](const CplusPlus::Document::Ptr &doc, +// // const CPlusPlus::Snapshot &snapshot) { +// // checkForQtTestStuff(doc, snapshot); +// // }); +// connect(cppMM, SIGNAL(documentUpdated(CPlusPlus::Document::Ptr)), +// this, SLOT(checkForQtTestStuff(CPlusPlus::Document::Ptr)), +// Qt::DirectConnection); + +// } +} + +static TestTreeModel *m_instance = 0; + +TestTreeModel *TestTreeModel::instance() +{ + if (!m_instance) + m_instance = new TestTreeModel; + return m_instance; +} + +TestTreeModel::~TestTreeModel() +{ + delete m_rootItem; + m_instance = 0; +} + +QModelIndex TestTreeModel::index(int row, int column, const QModelIndex &parent) const +{ + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + TestTreeItem *parentItem = parent.isValid() + ? static_cast(parent.internalPointer()) + : m_rootItem; + + TestTreeItem *childItem = parentItem->child(row); + return childItem ? createIndex(row, column, childItem) : QModelIndex(); +} + +QModelIndex TestTreeModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) + return QModelIndex(); + + TestTreeItem *childItem = static_cast(index.internalPointer()); + TestTreeItem *parentItem = childItem->parent(); + + if (parentItem == m_rootItem) + return QModelIndex(); + + return createIndex(parentItem->row(), 0, parentItem); +} + +bool TestTreeModel::hasChildren(const QModelIndex &parent) const +{ + if (!parent.isValid()) + return true; + + TestTreeItem *item = static_cast(parent.internalPointer()); + return item->childCount() > 0; +} + +int TestTreeModel::rowCount(const QModelIndex &parent) const +{ + TestTreeItem *parentItem = parent.isValid() + ? static_cast(parent.internalPointer()) : m_rootItem; + return parentItem->childCount(); +} + +int TestTreeModel::columnCount(const QModelIndex &) const +{ + return 1; +} + +QVariant TestTreeModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + TestTreeItem *item = static_cast(index.internalPointer()); + if (!item) + return QVariant(); + + if (role == Qt::DisplayRole) { + if ((item == m_autoTestRootItem && m_autoTestRootItem->childCount() == 0) + /*|| (item == m_quickTestRootItem && m_quickTestRootItem->childCount() == 0)*/) { + return QString(item->name() + tr(" (none)")); + } else { + return item->name(); + } + + return QVariant(); // TODO ? + } + switch(role) { + case Qt::ToolTipRole: + return item->filePath(); + case Qt::DecorationRole: + switch(item->type()) { + case TestTreeItem::TEST_CLASS: + return QIcon(QLatin1String(":/images/class.png")); + case TestTreeItem::TEST_FUNCTION: + return QIcon(QLatin1String(":/images/func.png")); + case TestTreeItem::ROOT: + default: + return QVariant(); + } + case Qt::CheckStateRole: + if (item->type() == TestTreeItem::ROOT) + return QVariant(); + return item->checked(); + case LinkRole: + QVariant itemLink; + TextEditor::TextEditorWidget::Link link(item->filePath(), item->line(), item->column()); + itemLink.setValue(link); + return itemLink; + } + + // TODO ? + return QVariant(); +} + +bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid()) + return false; + + if (role == Qt::CheckStateRole) { + TestTreeItem *item = static_cast(index.internalPointer()); + Qt::CheckState old = item->checked(); + item->setChecked((Qt::CheckState)value.toInt()); + if (item->checked() != old) { + switch(item->type()) { + case TestTreeItem::TEST_CLASS: + emit dataChanged(index, index); + if (item->childCount() > 0) { + emit dataChanged(index.child(0, 0), index.child(item->childCount() - 1, 0)); + } + break; + case TestTreeItem::TEST_FUNCTION: + emit dataChanged(index, index); + emit dataChanged(index.parent(), index.parent()); + break; + default: // avoid warning regarding unhandled enum member + break; + } + return true; + } + } + return false; +} + +Qt::ItemFlags TestTreeModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + + TestTreeItem *item = static_cast(index.internalPointer()); + switch(item->type()) { + case TestTreeItem::TEST_CLASS: + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsTristate | Qt::ItemIsUserCheckable; + case TestTreeItem::TEST_FUNCTION: + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable; + case TestTreeItem::ROOT: + default: + return Qt::ItemIsEnabled; + } +} + +bool TestTreeModel::removeRows(int row, int count, const QModelIndex &parent) +{ + if (!parent.isValid()) + return false; + TestTreeItem *parentItem = static_cast(parent.internalPointer()); + if (!parentItem) + return false; + + bool subItemsSuccess = true; + bool itemSuccess = true; + for (int i = row + count - 1; i >= row; --i) { + QModelIndex child = index(i, 0, parent); + subItemsSuccess &= removeRows(0, rowCount(child), child); + beginRemoveRows(parent, i, i); + itemSuccess &= parentItem->removeChild(i); + endRemoveRows(); + } + return subItemsSuccess && itemSuccess; +} + +bool TestTreeModel::hasTests() const +{ + return m_autoTestRootItem->childCount() > 0 /*|| m_quickTestRootItem->childCount() > 0*/; +} + +void TestTreeModel::modifyAutoTestSubtree(int row, TestTreeItem *newItem) +{ + static QVector modificationRoles = QVector() << Qt::DisplayRole + << Qt::ToolTipRole << LinkRole; + QModelIndex toBeModifiedIndex = index(0, 0).child(row, 0); + if (!toBeModifiedIndex.isValid()) + return; + TestTreeItem *toBeModifiedItem = static_cast(toBeModifiedIndex.internalPointer()); + if (toBeModifiedItem->modifyContent(newItem)) + emit dataChanged(toBeModifiedIndex, toBeModifiedIndex, modificationRoles); + + // process sub-items as well... + int childCount = toBeModifiedItem->childCount(); + int newChildCount = newItem->childCount(); + + // for keeping the CheckState on modifications + QHash originalItems; + for (int row = 0; row < childCount; ++row) { + const TestTreeItem *child = toBeModifiedItem->child(row); + originalItems.insert(child->name(), child->checked()); + } + + if (childCount <= newChildCount) { + for (int row = 0; row < childCount; ++row) { + QModelIndex child = toBeModifiedIndex.child(row, 0); + TestTreeItem *toBeModifiedChild = toBeModifiedItem->child(row); + TestTreeItem *modifiedChild = newItem->child(row); + if (toBeModifiedChild->modifyContent(modifiedChild)) { + emit dataChanged(child, child, modificationRoles); + } + if (originalItems.contains(toBeModifiedChild->name())) { + Qt::CheckState state = originalItems.value(toBeModifiedChild->name()); + if (state != toBeModifiedChild->checked()) { + toBeModifiedChild->setChecked(state); + emit dataChanged(child, child, QVector() << Qt::CheckStateRole); + } + } else { // newly added (BAD: happens for renaming as well) + toBeModifiedChild->setChecked(Qt::Checked); + emit dataChanged(child, child, QVector() << Qt::CheckStateRole); + } + } + if (childCount < newChildCount) { // add aditional items + for (int row = childCount; row < newChildCount; ++row) { + TestTreeItem *newChild = newItem->child(row); + TestTreeItem *toBeAdded = new TestTreeItem(newChild->name(), newChild->filePath(), + newChild->type(), toBeModifiedItem); + toBeAdded->setLine(newChild->line()); + beginInsertRows(toBeModifiedIndex, row, row); + toBeModifiedItem->appendChild(toBeAdded); + endInsertRows(); + if (originalItems.contains(toBeAdded->name()) + && originalItems.value(toBeAdded->name()) != Qt::Checked) + toBeAdded->setChecked(originalItems.value(toBeAdded->name())); + } + } + } else { + for (int row = 0; row < newChildCount; ++row) { + QModelIndex child = toBeModifiedIndex.child(row, 0); + TestTreeItem *toBeModifiedChild = toBeModifiedItem->child(row); + TestTreeItem *modifiedChild = newItem->child(row); + if (toBeModifiedChild->modifyContent(modifiedChild)) + emit dataChanged(child, child, modificationRoles); + if (originalItems.contains(toBeModifiedChild->name())) { + Qt::CheckState state = originalItems.value(toBeModifiedChild->name()); + if (state != toBeModifiedChild->checked()) { + toBeModifiedChild->setChecked(state); + emit dataChanged(child, child, QVector() << Qt::CheckStateRole); + } + } else { // newly added (BAD: happens for renaming as well) + toBeModifiedChild->setChecked(Qt::Checked); + emit dataChanged(child, child, QVector() << Qt::CheckStateRole); + } + } // remove rest of the items + removeRows(newChildCount, childCount - newChildCount, toBeModifiedIndex); + } +} + +void TestTreeModel::removeAutoTestSubtreeByFilePath(const QString &file) +{ + QModelIndex atRootIndex = index(0, 0); + int count = rowCount(atRootIndex); + for (int row = 0; row < count; ++row) { + QModelIndex childIndex = atRootIndex.child(row, 0); + TestTreeItem *childItem = static_cast(childIndex.internalPointer()); + if (file == childItem->filePath()) { + removeRow(row, atRootIndex); + break; + } + } +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h new file mode 100644 index 00000000000..9ec25f04762 --- /dev/null +++ b/plugins/autotest/testtreemodel.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTTREEMODEL_H +#define TESTTREEMODEL_H + +#include + +#include + +namespace { + enum ItemRole { +// AnnotationRole = Qt::UserRole + 1, + LinkRole = Qt::UserRole + 2 // can be removed if AnnotationRole comes back + }; +} + +namespace Autotest { +namespace Internal { + +class TestCodeParser; +class TestInfo; +class TestTreeItem; + +class TestTreeModel : public QAbstractItemModel +{ + Q_OBJECT +public: + static TestTreeModel* instance(); + ~TestTreeModel(); + + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + bool hasChildren(const QModelIndex &parent) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + bool setData(const QModelIndex &index, const QVariant &value, int role); + Qt::ItemFlags flags(const QModelIndex &index) const; + bool removeRows(int row, int count, const QModelIndex &parent); + + TestCodeParser *parser() const { return m_parser; } + bool hasTests() const; + +signals: + +public slots: + +private: + void modifyAutoTestSubtree(int row, TestTreeItem *newItem); + void removeAutoTestSubtreeByFilePath(const QString &file); + explicit TestTreeModel(QObject *parent = 0); + + TestTreeItem *m_rootItem; + TestTreeItem *m_autoTestRootItem; +// TestTreeItem *m_quickTestRootItem; + TestCodeParser *m_parser; + + friend class TestCodeParser; +}; + +} // namespace Internal +} // namespace Autotest + +#endif // TESTTREEMODEL_H diff --git a/plugins/autotest/testtreeview.cpp b/plugins/autotest/testtreeview.cpp new file mode 100644 index 00000000000..04b2ffb60fb --- /dev/null +++ b/plugins/autotest/testtreeview.cpp @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "autotestconstants.h" +#include "testcodeparser.h" +#include "testtreeitem.h" +#include "testtreemodel.h" +#include "testtreeview.h" + +#include + +#include + +#include +#include + +#include + +#include +#include + +namespace Autotest { +namespace Internal { + +TestTreeViewWidget::TestTreeViewWidget(QWidget *parent) : + QWidget(parent) +{ + setWindowTitle(tr("Tests")); + m_model = TestTreeModel::instance(); + m_view = new TestTreeView(this); + m_view->setModel(m_model); + + QVBoxLayout *layout = new QVBoxLayout; + layout->setMargin(0); + layout->setSpacing(0); + layout->addWidget(m_view); + setLayout(layout); + + TestCodeParser *parser = m_model->parser(); + ProjectExplorer::SessionManager *sm = static_cast( + ProjectExplorer::SessionManager::instance()); + connect(sm, &ProjectExplorer::SessionManager::startupProjectChanged, + parser, &TestCodeParser::updateTestTree); + + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + connect(cppMM, &CppTools::CppModelManager::documentUpdated, + parser, &TestCodeParser::onDocumentUpdated, Qt::QueuedConnection); + + connect(cppMM, &CppTools::CppModelManager::aboutToRemoveFiles, + parser, &TestCodeParser::removeFiles, Qt::QueuedConnection); + + connect(m_view, &TestTreeView::activated, this, &TestTreeViewWidget::onItemActivated); +} + +void TestTreeViewWidget::contextMenuEvent(QContextMenuEvent *event) +{ + bool hasTests = m_model->hasTests(); + QMenu menu; + QAction *runAll = new QAction(tr("Run All Tests"), &menu); + QAction *runSelected = new QAction(tr("Run Selected Tests"), &menu); + QAction *selectAll = new QAction(tr("Select All"), &menu); + QAction *deselectAll = new QAction(tr("Deselect All"), &menu); + // TODO remove? + QAction *rescan = new QAction(tr("Rescan"), &menu); + + connect(selectAll, &QAction::triggered, m_view, &TestTreeView::selectAll); + connect(deselectAll, &QAction::triggered, m_view, &TestTreeView::deselectAll); + connect(rescan, &QAction::triggered, + TestTreeModel::instance()->parser(), &TestCodeParser::updateTestTree); + + runAll->setEnabled(hasTests); + runSelected->setEnabled(hasTests); + selectAll->setEnabled(hasTests); + deselectAll->setEnabled(hasTests); + + menu.addAction(runAll); + menu.addAction(runSelected); + menu.addSeparator(); + menu.addAction(selectAll); + menu.addAction(deselectAll); + menu.addSeparator(); + menu.addAction(rescan); + + menu.exec(mapToGlobal(event->pos())); +} + +QList TestTreeViewWidget::createToolButtons() +{ + QList list; + + m_sort = new QToolButton(this); + m_sort->setIcon((QIcon(QLatin1String(":/images/sort.png")))); + m_sort->setToolTip(tr("Sort Alphabetically (not implemented yet)")); // TODO + m_sort->setCheckable(true); + m_sort->setChecked(true); + + QToolButton *expand = new QToolButton(this); + expand->setIcon(QIcon(QLatin1String(":/images/expand.png"))); + expand->setToolTip(tr("Expand All")); + + QToolButton *collapse = new QToolButton(this); + collapse->setIcon(QIcon(QLatin1String(":/images/collapse.png"))); + collapse->setToolTip(tr("Collapse All")); + + connect(expand, &QToolButton::clicked, m_view, &TestTreeView::expandAll); + connect(collapse, &QToolButton::clicked, m_view, &TestTreeView::collapseAll); +// connect(m_sort, &QToolButton::toggled, m_view, &TestTreeView::onSortToggled); // TODO + + list << m_sort << expand << collapse; + return list; +} + +void TestTreeViewWidget::onItemActivated(const QModelIndex &index) +{ + const TextEditor::TextEditorWidget::Link link + = index.data(LinkRole).value(); + if (link.hasValidTarget()) { + Core::EditorManager::openEditorAt(link.targetFileName, + link.targetLine, + link.targetColumn); + } +} + +TestViewFactory::TestViewFactory() +{ + setDisplayName(tr("Tests")); + setId(Autotest::Constants::AUTOTEST_ID); + setPriority(666); +} + +Core::NavigationView TestViewFactory::createWidget() +{ + TestTreeViewWidget *treeView = new TestTreeViewWidget; + Core::NavigationView view; + view.widget = treeView; + view.dockToolBarWidgets = treeView->createToolButtons(); + return view; +} + +TestTreeView::TestTreeView(QWidget *parent) + : NavigationTreeView(parent), + m_context(new Core::IContext(this)) +{ + setExpandsOnDoubleClick(false); + m_context->setWidget(this); + m_context->setContext(Core::Context(Constants::AUTOTEST_CONTEXT)); + Core::ICore::addContextObject(m_context); +} + +void TestTreeView::selectAll() +{ + selectOrDeselectAll(Qt::Checked); +} + +void TestTreeView::deselectAll() +{ + selectOrDeselectAll(Qt::Unchecked); +} + +// this avoids the re-evaluation of parent nodes when modifying the child nodes (setData()) +void TestTreeView::selectOrDeselectAll(const Qt::CheckState checkState) +{ + TestTreeModel *model = TestTreeModel::instance(); + QModelIndex autoTestsIndex = model->index(0, 0, rootIndex()); + if (!autoTestsIndex.isValid()) + return; + int count = model->rowCount(autoTestsIndex); + QModelIndex last; + for (int i = 0; i < count; ++i) { + QModelIndex classesIndex = model->index(i, 0, autoTestsIndex); + int funcCount = model->rowCount(classesIndex); + TestTreeItem *item = static_cast(classesIndex.internalPointer()); + if (item) { + item->setChecked(checkState); + if (!item->childCount()) + last = classesIndex; + } + for (int j = 0; j < funcCount; ++j) { + last = model->index(j, 0, classesIndex); + TestTreeItem *item = static_cast(last.internalPointer()); + if (item) + item->setChecked(checkState); + } + } + emit dataChanged(autoTestsIndex, last); +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testtreeview.h b/plugins/autotest/testtreeview.h new file mode 100644 index 00000000000..cb66fa12ccb --- /dev/null +++ b/plugins/autotest/testtreeview.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTTREEVIEW_H +#define TESTTREEVIEW_H + +#include + +#include + +QT_BEGIN_NAMESPACE +class QModelIndex; +class QToolButton; +QT_END_NAMESPACE + +namespace Core { +class IContext; +} + +namespace Autotest { +namespace Internal { + +class TestTreeModel; + +class TestTreeView : public Utils::NavigationTreeView +{ + Q_OBJECT + +public: + TestTreeView(QWidget *parent = 0); + + void selectAll(); + void deselectAll(); + +private: + void selectOrDeselectAll(const Qt::CheckState checkState); + Core::IContext *m_context; +}; + + +class TestTreeViewWidget : public QWidget +{ + Q_OBJECT + +public: + explicit TestTreeViewWidget(QWidget *parent = 0); + void contextMenuEvent(QContextMenuEvent *event); + QList createToolButtons(); + +signals: + +public slots: + +private slots: + void onItemActivated(const QModelIndex &index); + +private: + TestTreeModel *m_model; + TestTreeView *m_view; + QToolButton *m_sort; + +}; + +class TestViewFactory : public Core::INavigationWidgetFactory +{ + Q_OBJECT + +public: + TestViewFactory(); + +private: + Core::NavigationView createWidget(); + +}; + +} // namespace Internal +} // namespace Autotest + +#endif // TESTTREEVIEW_H diff --git a/plugins/autotest/testvisitor.cpp b/plugins/autotest/testvisitor.cpp new file mode 100644 index 00000000000..4f83c9d55b3 --- /dev/null +++ b/plugins/autotest/testvisitor.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "testvisitor.h" + +#include +#include +#include + +#include + +namespace Autotest { +namespace Internal { + +TestVisitor::TestVisitor(const QString &fullQualifiedClassName) + : m_className(fullQualifiedClassName) +{ +} + +TestVisitor::~TestVisitor() +{ +} + +static QList ignoredFunctions = QList() << QLatin1String("initTestCase") + << QLatin1String("cleanupTestCase") + << QLatin1String("init") + << QLatin1String("cleanup"); + +bool TestVisitor::visit(CPlusPlus::Class *symbol) +{ + const CPlusPlus::Overview o; + CPlusPlus::LookupContext lc; + + unsigned count = symbol->memberCount(); + for (unsigned i = 0; i < count; ++i) { + CPlusPlus::Symbol *member = symbol->memberAt(i); + CPlusPlus::Type *type = member->type().type(); + + const QString className = o.prettyName(lc.fullyQualifiedName(member->enclosingClass())); + if (className != m_className) + continue; + + if (auto func = type->asFunctionType()) { + if (func->isSlot() && member->isPrivate()) { + QString name = o.prettyName(func->name()); + if (!ignoredFunctions.contains(name) && !name.endsWith(QLatin1String("_data"))) { + TestCodeLocation location; + location.m_fileName = QLatin1String(member->fileName()); + location.m_line = member->line(); + location.m_column = member->column() - 1; + m_privSlots.insert(name, location); + } + } + } + } + return true; +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testvisitor.h b/plugins/autotest/testvisitor.h new file mode 100644 index 00000000000..c3fafac6a96 --- /dev/null +++ b/plugins/autotest/testvisitor.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTVISITOR_H +#define TESTVISITOR_H + +#include + +#include +#include + +namespace Autotest { +namespace Internal { + +struct TestCodeLocation { + QString m_fileName; + unsigned m_line; + unsigned m_column; +}; + +class TestVisitor : public CPlusPlus::SymbolVisitor +{ +public: + TestVisitor(const QString &fullQualifiedClassName); + virtual ~TestVisitor(); + + QMap privateSlots() const { return m_privSlots; } + + bool visit(CPlusPlus::Class *symbol); + +private: + QString m_className; + QMap m_privSlots; +}; + +} // namespace Internal +} // namespace Autotest + +#endif // TESTVISITOR_H diff --git a/qtcreatorplugin.pri b/qtcreatorplugin.pri new file mode 100644 index 00000000000..190dbed1c3b --- /dev/null +++ b/qtcreatorplugin.pri @@ -0,0 +1,8 @@ +isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE=$$(QTC_SOURCE) +isEmpty(IDE_BUILD_TREE): IDE_BUILD_TREE=$$(QTC_BUILD) + +isEmpty(IDE_SOURCE_TREE):error(Set QTC_SOURCE environment variable) +isEmpty(IDE_BUILD_TREE):error(Set QTC_BUILD environment variable) + +INCLUDEPATH+= $$PWD/plugins +include($$IDE_SOURCE_TREE/src/qtcreatorplugin.pri) diff --git a/shared/autotest/auto.pro b/shared/autotest/auto.pro new file mode 100644 index 00000000000..b39fef654c3 --- /dev/null +++ b/shared/autotest/auto.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs + +SUBDIRS += %TestCaseName:l% diff --git a/shared/autotest/autotest_24.png b/shared/autotest/autotest_24.png new file mode 100644 index 0000000000000000000000000000000000000000..3f52e9bf08f153f408bdcf60bbf382d649796f87 GIT binary patch literal 683 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4rT@hhU+WOo?>8N3<&TEasB`QKLY~;Ljwat z0s})l7$tz&V3IMBktvahIf z<*UkT*VQ&`XlU8g(!Qm=b8Bb!_U`_j{S$Ugn7C`=q}`Jy@0mPx@6;LlXUyC`bMB$J z^AFEobac_u<4c#FShnKiiZ!R#tUtSc!?_I`&u!d(Y5R`LJN91Nd*H@_W4Di;ynFK8 zgL4-jUA*!9#@$zU@4vqP@Xf<#@1MQ+_~OmyH*deZegF0Shi@M~egE|N$LB9UzI^@p z_4}{yKY#!H_2<{`zrX+f`}^UtIM4p3*Lt5C8sKn_DL8&fi(P?%SDd zI{mUggm1@Z{Y>e(zUgd2G@~&Kmq3=Tv15kr>B~JTnJ+EBa+fjAm@abWLqK4Qo}Jrm z@rv9DN>4h(6pwZ-F+R35RP3hCAx%L~VIA-Ce$$)37jT=Gct}0)Nc>jn)6X5=qRP8@ zxnLUE3b5`eW`z-^I1?3dAj +@else +#include +@endif + +// add necessary includes here + +int main(int argc, char *argv[]) +{ +@if "%RequireGUI%" == "true" + QApplication a(argc, argv); +@else + QCoreApplication a(argc, argv); +@endif + + return a.exec(); +} diff --git a/shared/autotest/src.pro b/shared/autotest/src.pro new file mode 100644 index 00000000000..3d0e33848b6 --- /dev/null +++ b/shared/autotest/src.pro @@ -0,0 +1,10 @@ +@if "%RequireGUI%" == "true" +QT += gui widgets +@else +QT += console +CONFIG -= app_bundle +@endif + +TEMPLATE = app + +SOURCES += main.%CppSourceSuffix% diff --git a/shared/autotest/tests.pro b/shared/autotest/tests.pro new file mode 100644 index 00000000000..f9277000081 --- /dev/null +++ b/shared/autotest/tests.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs + +SUBDIRS += auto diff --git a/shared/autotest/tmp.pro b/shared/autotest/tmp.pro new file mode 100644 index 00000000000..1569bd45cb7 --- /dev/null +++ b/shared/autotest/tmp.pro @@ -0,0 +1,12 @@ +TEMPLATE = subdirs + +@if "%BuildTests%" == "always" +SUBDIRS += src \ + tests +@else +SUBDIRS += src + +CONFIG(debug, debug|release) { + SUBDIRS += tests +} +@endif diff --git a/shared/autotest/tst.pro b/shared/autotest/tst.pro new file mode 100644 index 00000000000..8aa61b767e7 --- /dev/null +++ b/shared/autotest/tst.pro @@ -0,0 +1,14 @@ +QT += testlib +@if "%RequireGUI%" == "false" +QT -= gui + +CONFIG += qt console warn_on depend_includepath testcase +CONFIG -= app_bundle +@else +QT += gui +CONFIG += qt warn_on depend_includepath testcase +@endif + +TEMPLATE = app + +SOURCES += tst_%TestCaseName:l%.%CppSourceSuffix% diff --git a/shared/autotest/tst_src.cpp b/shared/autotest/tst_src.cpp new file mode 100644 index 00000000000..65d49e9c18a --- /dev/null +++ b/shared/autotest/tst_src.cpp @@ -0,0 +1,58 @@ +#include +@if "%RequireApplication%" == "true" +#include +@endif + +// add necessary includes here + +class %TestCaseName% : public QObject +{ + Q_OBJECT + +public: + %TestCaseName%(); + ~%TestCaseName%(); + +private slots: +@if "%GenerateInitAndCleanup%" == "true" + void initTestCase(); + void cleanupTestCase(); +@endif + void test_case1(); + +}; + +%TestCaseName%::%TestCaseName%() +{ + +} + +%TestCaseName%::~%TestCaseName%() +{ + +} + +@if "%GenerateInitAndCleanup%" == "true" +void %TestCaseName%::initTestCase() +{ + +} + +void %TestCaseName%::cleanupTestCase() +{ + +} + +@endif +void %TestCaseName%::test_case1() +{ + +} + +@if "%RequireApplication%" == "true" +QTEST_MAIN(%TestCaseName%) +@else +QTEST_APPLESS_MAIN(%TestCaseName%) +@endif + +#include "tst_%TestCaseName:l%.moc" diff --git a/shared/autotest/wizard.xml b/shared/autotest/wizard.xml new file mode 100644 index 00000000000..a190405d389 --- /dev/null +++ b/shared/autotest/wizard.xml @@ -0,0 +1,92 @@ + + + + + autotest_24.png + Creates a new project including auto test skeleton. + Auto Test; + Other Project + + + + + + + + + + + Project and Test Information + + + + GUI Application + + + + Test Case Name: + + + + Requires QApplication + + + + Generate initialization and cleanup code + + + + + + always + + + debug only + + + + Build auto tests + + + diff --git a/shared/shared.pro b/shared/shared.pro new file mode 100644 index 00000000000..e74d4d09acd --- /dev/null +++ b/shared/shared.pro @@ -0,0 +1,10 @@ +TEMPLATE = aux + +content.files = \ + autotest + +content.path = $$QTC_PREFIX/share/qtcreator/templates/wizards + +OTHER_FILES += $${content.files} + +INSTALLS += content From 44db2be195b38316e238eddad80b816ab96b6058 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 7 Oct 2014 15:51:02 +0200 Subject: [PATCH 002/200] Provide basic test runner and output pane --- plugins/autotest/autotest.pro | 16 +- plugins/autotest/autotest.qrc | 11 + plugins/autotest/autotestplugin.cpp | 5 + plugins/autotest/images/debug.png | Bin 0 -> 621 bytes plugins/autotest/images/fail.png | Bin 0 -> 600 bytes plugins/autotest/images/fatal.png | Bin 0 -> 597 bytes plugins/autotest/images/leafsort.png | Bin 0 -> 415 bytes plugins/autotest/images/pass.png | Bin 0 -> 595 bytes plugins/autotest/images/run.png | Bin 0 -> 509 bytes plugins/autotest/images/runselected.png | Bin 0 -> 709 bytes plugins/autotest/images/skip.png | Bin 0 -> 368 bytes plugins/autotest/images/warn.png | Bin 0 -> 621 bytes plugins/autotest/images/xfail.png | Bin 0 -> 547 bytes plugins/autotest/images/xpass.png | Bin 0 -> 599 bytes plugins/autotest/testcodeparser.cpp | 5 +- plugins/autotest/testcodeparser.h | 2 +- plugins/autotest/testconfiguration.cpp | 71 +++++ plugins/autotest/testconfiguration.h | 78 +++++ plugins/autotest/testinfo.cpp | 5 + plugins/autotest/testinfo.h | 1 + plugins/autotest/testresult.cpp | 101 +++++++ plugins/autotest/testresult.h | 79 +++++ plugins/autotest/testresultdelegate.cpp | 244 ++++++++++++++++ plugins/autotest/testresultdelegate.h | 110 +++++++ plugins/autotest/testresultmodel.cpp | 163 +++++++++++ plugins/autotest/testresultmodel.h | 66 +++++ plugins/autotest/testresultspane.cpp | 216 ++++++++++++++ plugins/autotest/testresultspane.h | 91 ++++++ plugins/autotest/testrunner.cpp | 371 ++++++++++++++++++++++++ plugins/autotest/testrunner.h | 74 +++++ plugins/autotest/testtreemodel.cpp | 134 ++++++++- plugins/autotest/testtreemodel.h | 4 + plugins/autotest/testtreeview.cpp | 52 +++- plugins/autotest/testtreeview.h | 4 + 34 files changed, 1877 insertions(+), 26 deletions(-) create mode 100644 plugins/autotest/images/debug.png create mode 100644 plugins/autotest/images/fail.png create mode 100644 plugins/autotest/images/fatal.png create mode 100644 plugins/autotest/images/leafsort.png create mode 100644 plugins/autotest/images/pass.png create mode 100644 plugins/autotest/images/run.png create mode 100644 plugins/autotest/images/runselected.png create mode 100644 plugins/autotest/images/skip.png create mode 100644 plugins/autotest/images/warn.png create mode 100644 plugins/autotest/images/xfail.png create mode 100644 plugins/autotest/images/xpass.png create mode 100644 plugins/autotest/testconfiguration.cpp create mode 100644 plugins/autotest/testconfiguration.h create mode 100644 plugins/autotest/testresult.cpp create mode 100644 plugins/autotest/testresult.h create mode 100644 plugins/autotest/testresultdelegate.cpp create mode 100644 plugins/autotest/testresultdelegate.h create mode 100644 plugins/autotest/testresultmodel.cpp create mode 100644 plugins/autotest/testresultmodel.h create mode 100644 plugins/autotest/testresultspane.cpp create mode 100644 plugins/autotest/testresultspane.h create mode 100644 plugins/autotest/testrunner.cpp create mode 100644 plugins/autotest/testrunner.h diff --git a/plugins/autotest/autotest.pro b/plugins/autotest/autotest.pro index 19df6bcb2eb..566c6131d12 100644 --- a/plugins/autotest/autotest.pro +++ b/plugins/autotest/autotest.pro @@ -15,7 +15,13 @@ SOURCES += \ testvisitor.cpp \ testinfo.cpp \ testcodeparser.cpp \ - autotestplugin.cpp + autotestplugin.cpp \ + testrunner.cpp \ + testconfiguration.cpp \ + testresult.cpp \ + testresultspane.cpp \ + testresultmodel.cpp \ + testresultdelegate.cpp HEADERS += \ testtreeview.h \ @@ -26,7 +32,13 @@ HEADERS += \ testcodeparser.h \ autotestplugin.h \ autotest_global.h \ - autotestconstants.h + autotestconstants.h \ + testrunner.h \ + testconfiguration.h \ + testresult.h \ + testresultspane.h \ + testresultmodel.h \ + testresultdelegate.h RESOURCES += \ autotest.qrc diff --git a/plugins/autotest/autotest.qrc b/plugins/autotest/autotest.qrc index 53dee42e310..b4b47f100f6 100644 --- a/plugins/autotest/autotest.qrc +++ b/plugins/autotest/autotest.qrc @@ -5,5 +5,16 @@ images/expand.png images/collapse.png images/sort.png + images/leafsort.png + images/debug.png + images/fail.png + images/fatal.png + images/pass.png + images/skip.png + images/warn.png + images/xfail.png + images/xpass.png + images/run.png + images/runselected.png diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index b0da2c1cac8..7dcb029d905 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -18,8 +18,10 @@ #include "autotestplugin.h" #include "autotestconstants.h" +#include "testrunner.h" #include "testtreeview.h" #include "testtreemodel.h" +#include "testresultspane.h" #include #include @@ -48,6 +50,8 @@ AutotestPlugin::~AutotestPlugin() // Delete members TestTreeModel *model = TestTreeModel::instance(); delete model; + TestRunner *runner = TestRunner::instance(); + delete runner; } bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorString) @@ -74,6 +78,7 @@ bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorStri Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu); addAutoReleasedObject(new TestViewFactory); + addAutoReleasedObject(TestResultsPane::instance()); return true; } diff --git a/plugins/autotest/images/debug.png b/plugins/autotest/images/debug.png new file mode 100644 index 0000000000000000000000000000000000000000..e18bd157e4a53187cb30ea2ec9b3a948c8445ec0 GIT binary patch literal 621 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4rT@h1`S>QUm z*zlT}=>-N#xw%Prc!=BC$+)^og@ouvM#@J;DW#@b6c#EcCCNob$|onQ=HytHmZ}#Q ztCyE+R8(k`mb$jLs}&Y%R#k;`cB&T^#!Q~9T~%e-+^kVq2@zK>E7Pv6)vB-8s;$+m zt##{Ybc=__s6)VD5u8dy2I&s~)r1k4lHf+e)v?*)z=A6x& zbGK~C+q$)2+qRBWmHFJE4F?b_CxH+S5=z3cYv-FNQnyLa!_unIyQw9tS3~N1I977}|Sr0n;9dck`IB>JfJMut) zu)oyflmF|F>Q@*F2`hF)YIUv|VVy;AjiPR7f4^RsE!^M5V> z6uWg#&f1_`%kKUC=$>qUp)B_L(S5Zyvc9a?Iwi=fHZGfIM)A4FZ_7?w2OgcWSkLG4 z+AhEH9kap`Pt}WGj9~t1er&^&$}6W{v!u=wZ(rQj&to8$5qYjqHela9aVCjhiI%c-SRB7Bd2n#H`qyid!yWfCpKWfuXv(AdL$_xM2%eYS zk#*ptL-p^E+ak`a`u#V)?&i1O$5&o?9s7E=wuO380*l(@f`w~0Prh(~LDtrGi|b+w zr9U3a<9*Jby<5F?+qAo(2X}ZpvZ?8Cj4|nT$k$((GAW_nepjNxtYe+~_GLdT`0-+8 z#+NTX8zXKo@*Ga#dBpHworE}T;`C?Ft(n(%{Ste<*3A|~)9_-ulW#OI;4!YA1OYe|FDkU*11u*V}tc2hw-UZe41hd+xyZ@(&5s@0c!o>F#gb{MlgZ_3uRve_PUn z4Zel0yi^wV?N_g`Qg~J366QY3gz&^NPCL8sSGlim**4a9-cQTP_wuAA`@Vnrba?ugeXp;$|6&fYxotb=^TRvwPMSymyA;$raV$K0NLO~5 z^28H6Gpz0^%KXbH-JL&Av|FG5%6C5l#UmRZ8{{9D`md3(XQSbyn>v3_s&E|K9`y3% zqfejyevgix$}Aispk&XP|9HY>CdQz{hb3B>ninrV!pp2HpkQlM6n*{c<;f?X9Mzwe z`i`;hP>oCx!^M!U9f=dpJeANA@p%3@s9aC_n5w+TfspqHH8ejiae4Pf!CJP?l27+^ z((%%XclBlkMXAZm`?S4)<=i)>yv2^Uw`E?*`V$j>{Iks#2ZrTA2Umt=Mv5t3w|&Yi zbs}y-?E2*VJfXg$3>jClID8l9-kz~ksBEXtVG~>V7l+gnwu#@2i)LP0Alq&i>(0@5 zJLge|R*rbL$ceCIvtl)IjqSU$<$o-=@{8+C&Y|wZQnmrnAD(ERsS7`K z?`-$sy2o1t%!3Q;SkgsGtT%+Tx3Vscd%xaRz@qLo9liPTuRy>?m;b ze#(0#!y`%xTy-L8t0zS1T<+|RSR%->HfPOSrlzE|y;E7D|1)n4;@&Oe(RHFwI!MAZ zd!mVZ-hAIC@y^bRjk;y`XW!>D?wN3;UdeE2yy@(-t@eyPhNm3`Y}^7vW{FKOI5vf0 zPsa(XhN(MV{F(CfcipkVImwgQ88$JTV%XBL#&6Aniy0Y9L*_m)J2}~aM||tG=?wQg z^nBMGh^kgr@{f95%Mkd-S&;L1*n`S>+Dg(&MT`nr+i!0+tn7PoJiMX_wU#j-{ ztqt=o-yN&Z(R6p;9yO)+$&5d1_AxJ5IOUet^2^s5p2c3@yZZX;NQT)A?;ih~Xe%%= zc#`NOz6R~=T*a9_^Oy~G#^iAr6mcnix^-QrK{@-a^ZrWfzuWcSCy3YFKd-Tri@~J9 zm|^?cu+=d-VsF1MnaGfQMy{c&!^G1rdo91A&7q5qLMnl4!(u0O9{juA{on3$^Pm6P WcC~k^VmAW=1B0ilpUXO@geCw!YOzuP literal 0 HcmV?d00001 diff --git a/plugins/autotest/images/pass.png b/plugins/autotest/images/pass.png new file mode 100644 index 0000000000000000000000000000000000000000..33dbe44649ee7fd1fb99c57d79882cd52d16f877 GIT binary patch literal 595 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!toq&!_5Lo9liPCo4&QYdoV zKK{sY0xVp`EZIc3%V~5-g zy_05oS_10F*^R}Y-K}^(x4M39$uSWwo8840&ktADx@sOx)cH~F;KFpKpk3}<>*0r+ z3vJ)MnD_7K-J<)c^V06UJDva5Vcm(qa|YgB*|AmP&a%#5Tz_?JJucAlrs&(zPrsl3 zj$XgL=(p8`)sr3>$#+b?;Ii2MlK(9a;|!jpHXoCV9(}6Idu9|WmD!ao+!3JjM)sk} z<|CdAC9m(!NSy4V;&{tra@R5rwx%`LuYK(Qd3^2bYsm?03JeODizYMXz1iRt)!|{_ z_T*G~GOfy+Iw|v6PvuXPk7Lf>rlgvv}`A;P;-Q%=xp872@SAkb?bDLrt*yN;Z?tS+7_FIyqIqh@E#`=1|d3-&ju{B!4I5OCU(zCKpt z3xCOcYdwXX;WPKwTedIJh}&yw5k2Q_gY4b|rRL^|**Ry}^ z3##%pvg1|IkVe)?R8#LF26qn=uN&Sqek#IvR=R`#9i zgtO0f@iZ#@YrT*+VN1P#!vT$BZikGyF6OO|d>uVIf@j&rn7Il&?@BQ;F1EN*w11<> z)eraL9Rls1@_${s^)I`C)ZIVJvke12*gpz>t7;#@_4}kQgM$gf>Z?N6R^@LDsdT&~ zlaj~S@MD$Av!=?Lu>PN_cWlnwD43|g`Q%pE#Nu_=-@Dr`+IP;0gTe~DWM4f{&?&L literal 0 HcmV?d00001 diff --git a/plugins/autotest/images/runselected.png b/plugins/autotest/images/runselected.png new file mode 100644 index 0000000000000000000000000000000000000000..328974062effb73ad838265bb8baaf0839525033 GIT binary patch literal 709 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!todOTemLo9liPLB7O94K*Y z{$m;4%}c+ee?FfQ5y;ZzGGUS+XRn)Y(<0qho4WI6U2whIBfzrQ(X(l~Xs1h^N0Q)G zjCgF9EDXnH z?0lQ@*|^TKI9u_P`mWGK1%VmcZsts7IPiIoqd?1w%P;rzn6g?|x7&Wa_dGml?({wz zrT|};8+)EVe||JZ&)wVGJ7xRrmHYSGd%3W(GHjW%?$ScN>c6eRTkplXXUm>VpC#vR zuVbg8B+Jm&*0!znaN?09!!2939C%v9$q=xS?ZVGJKAfh_qNf%e%(cE#wf^e<|IZG- zob_#1H^YUych|N!DMqXfE0AGde9=R-VTn?p(@BMeX%hleK7>|=mEOITxa+b>(w=SK zOSRNDUA!3R&6?op;m3T?41o*xi3()gb#_{&%k3{^f=%PdzY|^bB?Ln(RHliGk$^D@(Y$f#x@% ziD8TkE-p=KuQ^?#q!okj@i1sHHtl2b{O#y+D~(@a1*`CMQBKKN&DVDgS1*X50p5C|@Jw4Yv6Zm&6Cmf*ciw^!9Z**H6MrK#e!si|4)C(kbl zrG^bUhV#HPfgCnyLUgIp8s!Z ae#;D7rPd$vXBZe57(8A5T-G@yGywq9U!=GI literal 0 HcmV?d00001 diff --git a/plugins/autotest/images/warn.png b/plugins/autotest/images/warn.png new file mode 100644 index 0000000000000000000000000000000000000000..a813c1dc9a6478e754aa3f62c40e14bf0f7c814c GIT binary patch literal 621 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!toOgvp2Lo9liPWJYg5-4)K z{(JQqZ)sggmv+VYr;8T|O*(Lb>voGk)0YKiiY$Vn8Z4@7Z;1%*SQW-9rg24WQV)+) z*7Q`bwN(==BUc*C>N39n_g(qzC&zy@bp0z3`(ALa|ML#_jI}@IBTvgZaXfzI%BS9S zQ?j$=HP7w?g>xR9P6@KJy=(ZZz_q4~^?3A=w%Y0!cS26qU5@is2x*hmI=1E0N1KBu zZa=xZZ(sRa^IiM=*Q|K(L@=;u#mscq)+4P38=E;>?-vi_UxKe?3B{$s6D6Ee@Btfsjn~-oI16wDr>L#=8G3ujW}DNu4(1sZ)={WS>bYo>MeV1y9*OWxn|I z?(*&P^KLT>uVB|YoEzqu{PM*TkBQ3e({$9-b}gH1H*sH{#4(>QQD1Vtx^Dec-cmWu zBbl+sxUaLb)wNGX(ujp)!$G!tiSIi$zp!BvV>Dsdx=7FP@E`eW9Lg;mf@(dTp7U&i zeI_b6ws2h2e7)@F4V&xC6OzyEpK&gKYv$!eu5+zISD9o!dZfhe!Y#*p?yGW(#XI&l z8{K=Q`1oG0dHitU;^gGbhyBE-W%zw(?CO)>a9S@q$MBd010SE1lxfx!&CMs(L|0bS zIyA38P-&miYs#|FPnMavb&(^p^lTwjtFq+`4IKx##6M0*WwpO-v;UHfkGBkQIAXLXD0a7tlNP%3EGS-nS2>iE&e%%|@t zy!*Z)@%oB+D_NIWb{;fjnXbj!RWl{}Q`v&@{m=h!H%IX?tu&5(#=yY9;OXk;vd$@? F2>^vX?UMii literal 0 HcmV?d00001 diff --git a/plugins/autotest/images/xpass.png b/plugins/autotest/images/xpass.png new file mode 100644 index 0000000000000000000000000000000000000000..964bb4a181e56ac6bb3c5b60fdfaab16755f9f3f GIT binary patch literal 599 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!to{$Gm-I&?lq=ic2r=kwz`{mN0<|J2v4l~zi!Y51IJ zA=T@~ADNrGF8g-;bDQ^%-{yRKyY0_e*%*LdUEWSQEBwyY#@qWLeOSnLK6X=1Gw|xVd>)4({VV`pEf#Rs&-}{F66%7MmL- zCvvz23#Szu^Y%F}S>ONSfdcQ_w-KEz&MU7>mF_FHVYy@wQ*P|FaH`X9yT;dxR)vP_ z>{)m9!o2pSTMZL#AATrUb}%6J?<=iUK?n843ZFk$dK2dbufW+e59*5;BpJH2B-G084>`pARe0Z(+9l7G)_*@> z`A)Y2e7%-X_8+>2>C~`&>^LMjriXTE={|qm9B;E7gB#!Hgh)p$(autoTestRootIndex.internalPointer()); autoTestRootItem->removeChildren(); m_model->endResetModel(); - ProjectExplorer::SessionManager *session = static_cast( - ProjectExplorer::SessionManager::instance()); + ProjectExplorer::SessionManager *session = ProjectExplorer::SessionManager::instance(); if (!session || !session->hasProjects()) return; @@ -196,10 +195,10 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) m_cppDocMap.insert(file, new TestInfo(tc, privSlots.keys(), doc->revision(), doc->editorRevision())); + delete info; break; } } - delete info; delete ttItem; } else { m_model->beginInsertRows(autoTestRootIndex, autoTestRootItem->childCount(), autoTestRootItem->childCount()); diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 0ef4eedc333..1eaed0b063a 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -38,7 +38,7 @@ class TestCodeParser : public QObject { Q_OBJECT public: - explicit TestCodeParser(/*QObject*/TestTreeModel *parent = 0); + explicit TestCodeParser(TestTreeModel *parent = 0); signals: diff --git a/plugins/autotest/testconfiguration.cpp b/plugins/autotest/testconfiguration.cpp new file mode 100644 index 00000000000..22037989233 --- /dev/null +++ b/plugins/autotest/testconfiguration.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "testconfiguration.h" + +#include + +namespace Autotest { +namespace Internal { + +TestConfiguration::TestConfiguration(const QString &testClass, const QStringList &testCases, + QObject *parent) + : QObject(parent), + m_testClass(testClass), + m_testCases(testCases), + m_project(0) +{ +} + +TestConfiguration::~TestConfiguration() +{ + m_testCases.clear(); +} + +void TestConfiguration::setTargetFile(const QString &targetFile) +{ + m_targetFile = targetFile; +} + +void TestConfiguration::setTargetName(const QString &targetName) +{ + m_targetName = targetName; +} + +void TestConfiguration::setProFile(const QString &proFile) +{ + m_proFile = proFile; +} + +void TestConfiguration::setWorkingDirectory(const QString &workingDirectory) +{ + m_workingDir = workingDirectory; +} + +void TestConfiguration::setEnvironment(const Utils::Environment &env) +{ + m_environment = env; +} + +void TestConfiguration::setProject(ProjectExplorer::Project *project) +{ + m_project = project; +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testconfiguration.h b/plugins/autotest/testconfiguration.h new file mode 100644 index 00000000000..fa9545157b4 --- /dev/null +++ b/plugins/autotest/testconfiguration.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTCONFIGURATION_H +#define TESTCONFIGURATION_H + +#include + +#include +#include + +namespace ProjectExplorer { +class Project; +} + +namespace Autotest { +namespace Internal { + +class TestConfiguration : public QObject + +{ + Q_OBJECT +public: + explicit TestConfiguration(const QString &testClass, const QStringList &testCases, + QObject *parent = 0); + ~TestConfiguration(); + + void setTargetFile(const QString &targetFile); + void setTargetName(const QString &targetName); + void setProFile(const QString &proFile); + void setWorkingDirectory(const QString &workingDirectory); + void setEnvironment(const Utils::Environment &env); + void setProject(ProjectExplorer::Project *project); + + QString testClass() const { return m_testClass; } + QStringList testCases() const { return m_testCases; } + QString proFile() const { return m_proFile; } + QString targetFile() const { return m_targetFile; } + QString targetName() const { return m_targetName; } + QString workingDirectory() const { return m_workingDir; } + Utils::Environment environment() const { return m_environment; } + ProjectExplorer::Project *project() const { return m_project; } + + +signals: + +public slots: + +private: + QString m_testClass; + QStringList m_testCases; + QString m_proFile; + QString m_targetFile; + QString m_targetName; + QString m_workingDir; + Utils::Environment m_environment; + ProjectExplorer::Project *m_project; +}; + +} // namespace Internal +} // namespace Autotest + +#endif // TESTCONFIGURATION_H diff --git a/plugins/autotest/testinfo.cpp b/plugins/autotest/testinfo.cpp index 8e5850c84be..ad904e9a0f1 100644 --- a/plugins/autotest/testinfo.cpp +++ b/plugins/autotest/testinfo.cpp @@ -30,5 +30,10 @@ TestInfo::TestInfo(const QString &className, const QStringList &functions, unsig { } +TestInfo::~TestInfo() +{ + m_functions.clear(); +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testinfo.h b/plugins/autotest/testinfo.h index 378afcab589..bfb7ef33c5e 100644 --- a/plugins/autotest/testinfo.h +++ b/plugins/autotest/testinfo.h @@ -30,6 +30,7 @@ public: explicit TestInfo(const QString &className, const QStringList &functions = QStringList(), unsigned revision = 0, unsigned editorRevision = 0); + ~TestInfo(); const QString testClass() const { return m_className; } void setTestClass(const QString &className) { m_className = className; } const QStringList testFunctions() const { return m_functions; } diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp new file mode 100644 index 00000000000..c75ba31ac6f --- /dev/null +++ b/plugins/autotest/testresult.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "testresult.h" + +namespace Autotest { +namespace Internal { + +TestResult::TestResult(const QString &className, const QString &testCase, const QString &dataTag, + ResultType result, const QString &description) + : m_class(className), + m_case(testCase), + m_dataTag(dataTag), + m_result(result), + m_description(description), + m_line(0) +{ +} + +ResultType TestResult::resultFromString(const QString &resultString) +{ + if (resultString == QLatin1String("pass")) + return PASS; + if (resultString == QLatin1String("fail")) + return FAIL; + if (resultString == QLatin1String("xfail")) + return EXPECTED_FAIL; + if (resultString == QLatin1String("xpass")) + return UNEXPECTED_PASS; + if (resultString == QLatin1String("skip")) + return SKIP; + if (resultString == QLatin1String("qdebug")) + return MESSAGE_DEBUG; + if (resultString == QLatin1String("warn")) + return MESSAGE_WARN; + if (resultString == QLatin1String("qfatal")) + return MESSAGE_FATAL; + qDebug(" unexpected testresult..."); + qDebug(resultString.toLatin1()); + return UNKNOWN; +} + +QString TestResult::resultToString(const ResultType type) +{ + switch(type) { + case PASS: return QLatin1String("PASS"); + case FAIL: return QLatin1String("FAIL"); + case EXPECTED_FAIL: return QLatin1String("XFAIL"); + case UNEXPECTED_PASS: return QLatin1String("XPASS"); + case SKIP: return QLatin1String("SKIP"); + case MESSAGE_DEBUG: return QLatin1String("DEBUG"); + case MESSAGE_WARN: return QLatin1String("WARN"); + case MESSAGE_FATAL: return QLatin1String("FATAL"); + case MESSAGE_INTERNAL: return QString(); + default: + return QLatin1String("UNKNOWN"); + } +} + +QColor TestResult::colorForType(const ResultType type) +{ + switch(type) { + case PASS: return QColor("#009900"); + case FAIL: return QColor("#a00000"); + case EXPECTED_FAIL: return QColor("#00ff00"); + case UNEXPECTED_PASS: return QColor("#ff0000"); + case SKIP: return QColor("#787878"); + case MESSAGE_DEBUG: return QColor("#329696"); + case MESSAGE_WARN: return QColor("#d0bb00"); + case MESSAGE_FATAL: return QColor("#640000"); + case MESSAGE_INTERNAL: return QColor("transparent"); + default: + return QColor("#000000"); + } +} + +bool operator==(const TestResult &t1, const TestResult &t2) +{ + return t1.className() == t2.className() + && t1.testCase() == t2.testCase() + && t1.dataTag() == t2.dataTag() + && t1.result() == t2.result(); +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h new file mode 100644 index 00000000000..dc476916645 --- /dev/null +++ b/plugins/autotest/testresult.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTRESULT_H +#define TESTRESULT_H + +#include +#include + +namespace Autotest { +namespace Internal { + +enum ResultType { + PASS, + FAIL, + EXPECTED_FAIL, + UNEXPECTED_PASS, + SKIP, + MESSAGE_DEBUG, + MESSAGE_WARN, + MESSAGE_FATAL, + MESSAGE_INTERNAL, + UNKNOWN // ??? +}; + +class TestResult +{ +public: + + TestResult(const QString &className, const QString &testCase, const QString &dataTag = QString(), + ResultType result = UNKNOWN, const QString &description = QString()); + + QString className() const { return m_class; } + QString testCase() const { return m_case; } + QString dataTag() const { return m_dataTag; } + ResultType result() const { return m_result; } + QString description() const { return m_description; } + QString fileName() const { return m_file; } + int line() const { return m_line; } + + void setFileName(const QString &fileName) { m_file = fileName; } + void setLine(int line) { m_line = line; } + + static ResultType resultFromString(const QString &resultString); + static QString resultToString(const ResultType type); + static QColor colorForType(const ResultType type); + +private: + QString m_class; + QString m_case; + QString m_dataTag; + ResultType m_result; + QString m_description; + QString m_file; + int m_line; + // environment? +}; + +bool operator==(const TestResult &t1, const TestResult &t2); + +} // namespace Internal +} // namespace Autotest + +#endif // TESTRESULT_H diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp new file mode 100644 index 00000000000..1f423d2e3a1 --- /dev/null +++ b/plugins/autotest/testresultdelegate.cpp @@ -0,0 +1,244 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "testresultdelegate.h" +#include "testresultmodel.h" + +#include +#include +#include +#include + +namespace Autotest { +namespace Internal { + +TestResultDelegate::TestResultDelegate(QObject *parent) + : QStyledItemDelegate(parent) +{ +} + +TestResultDelegate::~TestResultDelegate() +{ + +} + +void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyleOptionViewItemV4 opt = option; + initStyleOption(&opt, index); + painter->save(); + + QFontMetrics fm(opt.font); + QColor background; + QColor foreground; + + const QAbstractItemView *view = qobject_cast(opt.widget); + const bool selected = view->selectionModel()->currentIndex() == index; + + if (selected) { + painter->setBrush(opt.palette.highlight().color()); + background = opt.palette.highlight().color(); + foreground = opt.palette.highlightedText().color(); + } else { + painter->setBrush(opt.palette.background().color()); + background = opt.palette.background().color(); + foreground = opt.palette.text().color(); + } + + painter->setPen(Qt::NoPen); + painter->drawRect(opt.rect); + + painter->setPen(foreground); + TestResultModel *resultModel = static_cast(view->model()); + LayoutPositions positions(opt, resultModel); + TestResult testResult = resultModel->testResult(index); + ResultType type = testResult.result(); + + QIcon icon = index.data(Qt::DecorationRole).value(); + if (!icon.isNull()) + painter->drawPixmap(positions.left(), positions.top(), + icon.pixmap(positions.iconSize(), positions.iconSize())); + + QString typeStr = TestResult::resultToString(testResult.result()); + if (selected) { + painter->drawText(positions.typeAreaLeft(), positions.top() + fm.ascent(), typeStr); + } else { + QPen tmp = painter->pen(); + painter->setPen(TestResult::colorForType(testResult.result())); + painter->drawText(positions.typeAreaLeft(), positions.top() + fm.ascent(), typeStr); + painter->setPen(tmp); + } + + QString output; + switch (type) { + case ResultType::PASS: + case ResultType::FAIL: + case ResultType::EXPECTED_FAIL: + case ResultType::UNEXPECTED_PASS: + output = testResult.className() + QLatin1String("::") + testResult.testCase(); + if (!testResult.dataTag().isEmpty()) + output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); + if (selected && !testResult.description().isEmpty()) { + output.append(QLatin1Char('\n')); + output.append(testResult.description()); + } + break; + default: + output = testResult.description(); + if (!selected) + output = output.split(QLatin1Char('\n')).first(); + } + + QColor mix; + mix.setRgb( static_cast(0.7 * foreground.red() + 0.3 * background.red()), + static_cast(0.7 * foreground.green() + 0.3 * background.green()), + static_cast(0.7 * foreground.blue() + 0.3 * background.blue())); + + if (selected) { + int height = 0; + int leading = fm.leading(); + int firstLineBreak = output.indexOf(QLatin1Char('\n')); + output.replace(QLatin1Char('\n'), QChar::LineSeparator); + QTextLayout tl(output); + if (firstLineBreak != -1) { + QTextLayout::FormatRange fr; + fr.start = firstLineBreak; + fr.length = output.length() - firstLineBreak; + fr.format.setFontStyleHint(QFont::Monospace); + fr.format.setForeground(mix); + tl.setAdditionalFormats(QList() << fr); + } + tl.beginLayout(); + while (true) { + QTextLine tLine = tl.createLine(); + if (!tLine.isValid()) + break; + tLine.setLineWidth(positions.textAreaWidth()); + height += leading; + tLine.setPosition(QPoint(0, height)); + height += fm.ascent() + fm.descent(); + } + tl.endLayout(); + tl.draw(painter, QPoint(positions.textAreaLeft(), positions.top())); + + painter->setPen(mix); + + int bottomLine = positions.top() + fm.ascent() + height + leading; + painter->drawText(positions.textAreaLeft(), bottomLine, testResult.fileName()); + } else { + painter->setClipRect(positions.textArea()); + painter->drawText(positions.textAreaLeft(), positions.top() + fm.ascent(), output); + } + + QString file = testResult.fileName(); + const int pos = file.lastIndexOf(QLatin1Char('/')); + if (pos != -1) + file = file.mid(pos + 1); + + painter->setClipRect(positions.fileArea()); + painter->drawText(positions.fileAreaLeft(), positions.top() + fm.ascent(), file); + + + if (testResult.line()) { + QString line = QString::number(testResult.line()); + painter->setClipRect(positions.lineArea()); + painter->drawText(positions.lineAreaLeft(), positions.top() + fm.ascent(), line); + } + + painter->setClipRect(opt.rect); + painter->setPen(QColor::fromRgb(150, 150, 150)); + painter->drawLine(0, opt.rect.bottom(), opt.rect.right(), opt.rect.bottom()); + painter->restore(); +} + +QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyleOptionViewItemV4 opt = option; + initStyleOption(&opt, index); + + const QAbstractItemView *view = qobject_cast(opt.widget); + const bool selected = view->selectionModel()->currentIndex() == index; + + QFontMetrics fm(opt.font); + int fontHeight = fm.height(); + TestResultModel *resultModel = static_cast(view->model()); + LayoutPositions positions(opt, resultModel); + QSize s; + s.setWidth(opt.rect.width()); + + if (selected) { + TestResult testResult = resultModel->testResult(index); + + QString output; + switch (testResult.result()) { + case ResultType::PASS: + case ResultType::FAIL: + case ResultType::EXPECTED_FAIL: + case ResultType::UNEXPECTED_PASS: + output = testResult.className() + QLatin1String("::") + testResult.testCase(); + if (!testResult.dataTag().isEmpty()) + output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); + if (!testResult.description().isEmpty()) { + output.append(QLatin1Char('\n')); + output.append(testResult.description()); + } + break; + default: + output = testResult.description(); + } + + output.replace(QLatin1Char('\n'), QChar::LineSeparator); + + int height = 0; + int leading = fm.leading(); + QTextLayout tl(output); + tl.beginLayout(); + while (true) { + QTextLine line = tl.createLine(); + if (!line.isValid()) + break; + height += leading; + line.setPosition(QPoint(0, height)); + height += fm.ascent() + fm.descent(); + } + tl.endLayout(); + + s.setHeight(height + leading + 3 + (testResult.fileName().isEmpty() ? 0 : fontHeight)); + } else { + s.setHeight(fontHeight + 3); + } + + if (s.height() < positions.minimumHeight()) + s.setHeight(positions.minimumHeight()); + + return s; +} + +void TestResultDelegate::emitSizeHintChanged(const QModelIndex &index) +{ + emit sizeHintChanged(index); +} + +void TestResultDelegate::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + emit sizeHintChanged(current); + emit sizeHintChanged(previous); +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testresultdelegate.h b/plugins/autotest/testresultdelegate.h new file mode 100644 index 00000000000..2b85ae1076d --- /dev/null +++ b/plugins/autotest/testresultdelegate.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTRESULTDELEGATE_H +#define TESTRESULTDELEGATE_H + +#include "testresultmodel.h" + +#include + +namespace Autotest { +namespace Internal { + +class TestResultDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + explicit TestResultDelegate(QObject *parent = 0); + ~TestResultDelegate(); + + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + + void emitSizeHintChanged(const QModelIndex &index); + +signals: + +public slots: + void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); + +private: + class LayoutPositions + { + public: + LayoutPositions(QStyleOptionViewItemV4 &options, TestResultModel *model) + : m_totalWidth(options.rect.width()), + m_maxFileLength(model->maxWidthOfFileName(options.font)), + m_maxLineLength(model->maxWidthOfLineNumber(options.font)), + m_realFileLength(m_maxFileLength), + m_top(options.rect.top()), + m_bottom(options.rect.bottom()) + { + int flexibleArea = lineAreaLeft() - textAreaLeft() - ITEM_SPACING; + if (m_maxFileLength > flexibleArea / 2) + m_realFileLength = flexibleArea / 2; + m_fontHeight = QFontMetrics(options.font).height(); + m_typeAreaWidth = QFontMetrics(options.font).width(QLatin1String("XXXXXXXX")); + } + + int top() const { return m_top + ITEM_MARGIN; } + int left() const { return ITEM_MARGIN; } + int right() const { return m_totalWidth - ITEM_MARGIN; } + int bottom() const { return m_bottom; } + int minimumHeight() const { return ICON_SIZE + 2 * ITEM_MARGIN; } + + int iconSize() const { return ICON_SIZE; } + int fontHeight() const { return m_fontHeight; } + int typeAreaLeft() const { return left() + ICON_SIZE + ITEM_SPACING; } + int typeAreaWidth() const { return m_typeAreaWidth; } + int textAreaLeft() const { return typeAreaLeft() + m_typeAreaWidth + ITEM_SPACING; } + int textAreaWidth() const { return fileAreaLeft() - ITEM_SPACING - textAreaLeft(); } + int fileAreaLeft() const { return lineAreaLeft() - ITEM_SPACING - m_realFileLength; } + int lineAreaLeft() const { return right() - m_maxLineLength; } + + QRect typeArea() const { return QRect(typeAreaLeft(), top(), + typeAreaWidth(), m_fontHeight); } + QRect textArea() const { return QRect(textAreaLeft(), top(), + fileAreaLeft() - ITEM_SPACING, m_fontHeight); } + QRect fileArea() const { return QRect(fileAreaLeft(), top(), + lineAreaLeft() - ITEM_SPACING, m_fontHeight); } + + QRect lineArea() const { return QRect(lineAreaLeft(), top(), + m_maxLineLength, m_fontHeight); } + + private: + int m_totalWidth; + int m_maxFileLength; + int m_maxLineLength; + int m_realFileLength; + int m_top; + int m_bottom; + int m_fontHeight; + int m_typeAreaWidth; + + static const int ICON_SIZE = 16; + static const int ITEM_MARGIN = 2; + static const int ITEM_SPACING = 4; + + }; +}; + +} // namespace Internal +} // namespace Autotest + +#endif // TESTRESULTDELEGATE_H diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp new file mode 100644 index 00000000000..1867987aa1f --- /dev/null +++ b/plugins/autotest/testresultmodel.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "testresultmodel.h" + +#include +#include +#include + +namespace Autotest { +namespace Internal { + +TestResultModel::TestResultModel(QObject *parent) : + QAbstractItemModel(parent), + m_widthOfLineNumber(0), + m_maxWidthOfFileName(0), + m_lastMaxWidthIndex(0) +{ +} + +TestResultModel::~TestResultModel() +{ + m_testResults.clear(); +} + +QModelIndex TestResultModel::index(int row, int column, const QModelIndex &parent) const +{ + if (parent.isValid()) + return QModelIndex(); + return createIndex(row, column); +} + +QModelIndex TestResultModel::parent(const QModelIndex &) const +{ + return QModelIndex(); +} + +int TestResultModel::rowCount(const QModelIndex &parent) const +{ + return parent.isValid() ? 0 : m_testResults.size(); +} + +int TestResultModel::columnCount(const QModelIndex &parent) const +{ + return parent.isValid() ? 0 : 1; +} + +static QIcon testResultIcon(ResultType result) { + static QIcon icons[8] = { + QIcon(QLatin1String(":/images/pass.png")), + QIcon(QLatin1String(":/images/fail.png")), + QIcon(QLatin1String(":/images/xfail.png")), + QIcon(QLatin1String(":/images/xpass.png")), + QIcon(QLatin1String(":/images/skip.png")), + QIcon(QLatin1String(":/images/debug.png")), + QIcon(QLatin1String(":/images/warn.png")), + QIcon(QLatin1String(":/images/fatal.png")), + }; + + if (result < 0 || result >= MESSAGE_INTERNAL) + return QIcon(); + return icons[result]; +} + +QVariant TestResultModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() >= m_testResults.count() || index.column() != 0) + return QVariant(); + if (role == Qt::DisplayRole) { + const TestResult &tr = m_testResults.at(index.row()); + switch (tr.result()) { + case ResultType::PASS: + case ResultType::FAIL: + case ResultType::EXPECTED_FAIL: + case ResultType::UNEXPECTED_PASS: + case ResultType::SKIP: + return QString::fromLatin1("%1::%2 (%3) - %4").arg(tr.className(), tr.testCase(), + tr.dataTag(), tr.fileName()); + default: + return tr.description(); + } + } + if (role == Qt::DecorationRole) { + const TestResult &tr = m_testResults.at(index.row()); + return testResultIcon(tr.result()); + } + + return QVariant(); +} + +void TestResultModel::addTestResult(const TestResult &testResult) +{ + beginInsertRows(QModelIndex(), m_testResults.size(), m_testResults.size()); + m_testResults.append(testResult); + endInsertRows(); +} + +void TestResultModel::clearTestResults() +{ + if (m_testResults.size() == 0) + return; + beginRemoveRows(QModelIndex(), 0, m_testResults.size() - 1); + m_testResults.clear(); + endRemoveRows(); +} + +TestResult TestResultModel::testResult(const QModelIndex &index) const +{ + if (!index.isValid()) + return TestResult(QString(), QString()); + return m_testResults.at(index.row()); +} + +int TestResultModel::maxWidthOfFileName(const QFont &font) +{ + int count = m_testResults.size(); + if (count == 0) + return 0; + if (m_maxWidthOfFileName > 0 && font == m_measurementFont && m_lastMaxWidthIndex == count - 1) + return m_maxWidthOfFileName; + + QFontMetrics fm(font); + m_measurementFont = font; + + for (int i = m_lastMaxWidthIndex; i < count; ++i) { + QString filename = m_testResults.at(i).fileName(); + const int pos = filename.lastIndexOf(QLatin1Char('/')); + if (pos != -1) + filename = filename.mid(pos +1); + + m_maxWidthOfFileName = qMax(m_maxWidthOfFileName, fm.width(filename)); + } + m_lastMaxWidthIndex = count - 1; + return m_maxWidthOfFileName; +} + +int TestResultModel::maxWidthOfLineNumber(const QFont &font) +{ + if (m_widthOfLineNumber == 0 || font != m_measurementFont) { + QFontMetrics fm(font); + m_measurementFont = font; + m_widthOfLineNumber = fm.width(QLatin1String("88888")); + } + return m_widthOfLineNumber; +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testresultmodel.h b/plugins/autotest/testresultmodel.h new file mode 100644 index 00000000000..fa358205546 --- /dev/null +++ b/plugins/autotest/testresultmodel.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTRESULTMODEL_H +#define TESTRESULTMODEL_H + +#include "testresult.h" + +#include +#include + +namespace Autotest { +namespace Internal { + +class TestResultModel : public QAbstractItemModel +{ + Q_OBJECT +public: + explicit TestResultModel(QObject *parent = 0); + ~TestResultModel(); + QModelIndex index(int row, int column, const QModelIndex &parent) const; + QModelIndex parent(const QModelIndex &) const; + int rowCount(const QModelIndex &parent) const; + int columnCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + + void addTestResult(const TestResult &testResult); + void clearTestResults(); + + bool hasResults() const { return m_testResults.size() > 0; } + TestResult testResult(const QModelIndex &index) const; + + int maxWidthOfFileName(const QFont &font); + int maxWidthOfLineNumber(const QFont &font); + +signals: + +public slots: + +private: + QList m_testResults; + int m_widthOfLineNumber; + int m_maxWidthOfFileName; + int m_lastMaxWidthIndex; + QFont m_measurementFont; +}; + +} // namespace Internal +} // namespace Autotest + +#endif // TESTRESULTMODEL_H diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp new file mode 100644 index 00000000000..100de73e58b --- /dev/null +++ b/plugins/autotest/testresultspane.cpp @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "testresultspane.h" +#include "testresultmodel.h" +#include "testresultdelegate.h" +#include "testrunner.h" +#include "testtreemodel.h" + +#include + +#include + +#include + +#include + +namespace Autotest { +namespace Internal { + +TestResultsPane::TestResultsPane(QObject *parent) : + Core::IOutputPane(parent), + m_context(new Core::IContext(this)) +{ + m_listView = new Utils::ListView; + m_model = new TestResultModel(this); + m_listView->setModel(m_model); + TestResultDelegate *trd = new TestResultDelegate(this); + m_listView->setItemDelegate(trd); + + createToolButtons(); + + connect(m_listView, &Utils::ListView::activated, this, &TestResultsPane::onItemActivated); + connect(m_listView->selectionModel(), &QItemSelectionModel::currentChanged, + trd, &TestResultDelegate::currentChanged); +} + +void TestResultsPane::createToolButtons() +{ + m_runAll = new QToolButton(m_listView); + m_runAll->setIcon(QIcon(QLatin1String(":/images/run.png"))); + m_runAll->setToolTip(tr("Run All Tests")); + connect(m_runAll, &QToolButton::clicked, this, &TestResultsPane::onRunAllTriggered); + + m_runSelected = new QToolButton(m_listView); + m_runSelected->setIcon(QIcon(QLatin1String(":/images/runselected.png"))); + m_runSelected->setToolTip(tr("Run Selected Tests")); + connect(m_runSelected, &QToolButton::clicked, this, &TestResultsPane::onRunSelectedTriggered); +} + +static TestResultsPane *m_instance = 0; + +TestResultsPane *TestResultsPane::instance() +{ + if (!m_instance) + m_instance = new TestResultsPane; + return m_instance; +} + +TestResultsPane::~TestResultsPane() +{ + delete m_listView; + m_instance = 0; +} + +void TestResultsPane::addTestResult(const TestResult &result) +{ + m_model->addTestResult(result); + if (!m_listView->isVisible()) + popup(Core::IOutputPane::NoModeSwitch); + flash(); + navigateStateChanged(); +} + +QWidget *TestResultsPane::outputWidget(QWidget *parent) +{ + if (m_listView) { + m_listView->setParent(parent); + } else { + m_listView = new Utils::ListView(parent); + } + return m_listView; +} + +QList TestResultsPane::toolBarWidgets() const +{ + return QList() << m_runAll << m_runSelected; // add filter as well +} + +QString TestResultsPane::displayName() const +{ + return tr("Test Results"); +} + +int TestResultsPane::priorityInStatusBar() const +{ + return -666; +} + +void TestResultsPane::clearContents() +{ + m_model->clearTestResults(); + navigateStateChanged(); +} + +void TestResultsPane::visibilityChanged(bool) +{ +} + +void TestResultsPane::setFocus() +{ +} + +bool TestResultsPane::hasFocus() const +{ + return m_listView->hasFocus(); +} + +bool TestResultsPane::canFocus() const +{ + return true; +} + +bool TestResultsPane::canNavigate() const +{ + return true; +} + +bool TestResultsPane::canNext() const +{ + return m_model->hasResults(); +} + +bool TestResultsPane::canPrevious() const +{ + return m_model->hasResults(); +} + +void TestResultsPane::goToNext() +{ + if (!canNext()) + return; + + QModelIndex currentIndex = m_listView->currentIndex(); + if (currentIndex.isValid()) { + int row = currentIndex.row() + 1; + if (row == m_model->rowCount(QModelIndex())) + row = 0; + currentIndex = m_model->index(row, 0, QModelIndex()); + } else { + currentIndex = m_model->index(0, 0, QModelIndex()); + } + m_listView->setCurrentIndex(currentIndex); + onItemActivated(currentIndex); +} + +void TestResultsPane::goToPrev() +{ + if (!canPrevious()) + return; + + QModelIndex currentIndex = m_listView->currentIndex(); + if (currentIndex.isValid()) { + int row = currentIndex.row() - 1; + if (row < 0) + row = m_model->rowCount(QModelIndex()) - 1; + currentIndex = m_model->index(row, 0, QModelIndex()); + } else { + currentIndex = m_model->index(m_model->rowCount(QModelIndex()) - 1, 0, QModelIndex()); + } + m_listView->setCurrentIndex(currentIndex); + onItemActivated(currentIndex); +} + +void TestResultsPane::onItemActivated(const QModelIndex &index) +{ + if (!index.isValid()) + return; + + TestResult tr = m_model->testResult(index); + if (!tr.fileName().isEmpty()) + Core::EditorManager::openEditorAt(tr.fileName(), tr.line(), 0); +} + +void TestResultsPane::onRunAllTriggered() +{ + TestRunner *runner = TestRunner::instance(); + runner->setSelectedTests(TestTreeModel::instance()->getAllTestCases()); + runner->runTests(); +} + +void TestResultsPane::onRunSelectedTriggered() +{ + TestRunner *runner = TestRunner::instance(); + runner->setSelectedTests(TestTreeModel::instance()->getSelectedTests()); + runner->runTests(); + +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h new file mode 100644 index 00000000000..28aff09103d --- /dev/null +++ b/plugins/autotest/testresultspane.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTRESULTSPANE_H +#define TESTRESULTSPANE_H + +#include + +QT_BEGIN_NAMESPACE +class QModelIndex; +class QToolButton; +QT_END_NAMESPACE + +namespace Core { +class IContext; +} + +namespace Utils { +class ListView; +} + +namespace Autotest { +namespace Internal { + +class TestResult; +class TestResultModel; + +class TestResultsPane : public Core::IOutputPane +{ + Q_OBJECT +public: + virtual ~TestResultsPane(); + static TestResultsPane *instance(); + + void addTestResult(const TestResult &result); + + // IOutputPane interface + QWidget *outputWidget(QWidget *parent); + QList toolBarWidgets() const; + QString displayName() const; + int priorityInStatusBar() const; + void clearContents(); + void visibilityChanged(bool); + void setFocus(); + bool hasFocus() const; + bool canFocus() const; + bool canNavigate() const; + bool canNext() const; + bool canPrevious() const; + void goToNext(); + void goToPrev(); + +signals: + +public slots: + +private slots: + void onItemActivated(const QModelIndex &index); + void onRunAllTriggered(); + void onRunSelectedTriggered(); + +private: + explicit TestResultsPane(QObject *parent = 0); + void createToolButtons(); + + Utils::ListView *m_listView; + TestResultModel *m_model; + Core::IContext *m_context; + QToolButton *m_runAll; + QToolButton *m_runSelected; +}; + +} // namespace Internal +} // namespace Autotest + +#endif // TESTRESULTSPANE_H diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp new file mode 100644 index 00000000000..5a1f41baefb --- /dev/null +++ b/plugins/autotest/testrunner.cpp @@ -0,0 +1,371 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "testresultspane.h" +#include "testrunner.h" + +#include // REMOVE + +#include +#include +#include +#include + +#include + +namespace Autotest { +namespace Internal { + +static TestRunner* m_instance = 0; + +TestRunner *TestRunner::instance() +{ + if (!m_instance) + m_instance = new TestRunner; + return m_instance; +} + +TestRunner::TestRunner(QObject *parent) : + QObject(parent), + m_building(false) +{ + m_runner.setReadChannelMode(QProcess::MergedChannels); + m_runner.setReadChannel(QProcess::StandardOutput); + + connect(&m_runner, &QProcess::readyReadStandardOutput, + this, &TestRunner::processOutput, Qt::DirectConnection); + connect(&m_runner, SIGNAL(finished(int,QProcess::ExitStatus)), + this, SLOT(onRunnerFinished(int,QProcess::ExitStatus)), Qt::DirectConnection); +} + +TestRunner::~TestRunner() +{ + qDeleteAll(m_selectedTests); + m_selectedTests.clear(); + m_instance = 0; +} + +void TestRunner::setSelectedTests(const QList &selected) +{ + qDeleteAll(m_selectedTests); + m_selectedTests.clear(); + m_selectedTests = selected; +} + +void TestRunner::runTests() +{ + if (m_selectedTests.empty()) { + TestResultsPane::instance()->addTestResult( + TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, + tr("*** No tests selected - canceling Test Run ***"))); + return; + } + + ProjectExplorer::Project *project = m_selectedTests.at(0)->project(); + + if (!project) {// add a warning or info to output? possible at all? + return; + } + + ProjectExplorer::ProjectExplorerPlugin *pep = ProjectExplorer::ProjectExplorerPlugin::instance(); + ProjectExplorer::Internal::ProjectExplorerSettings pes = pep->projectExplorerSettings(); + if (pes.buildBeforeDeploy) { + if (!project->hasActiveBuildSettings()) { + qDebug() << "no active build settings...???"; // let it configure? + return; + } + buildProject(project); + while (m_building) { + qApp->processEvents(); + } + + if (!m_buildSucceeded) { + TestResultsPane::instance()->addTestResult( + TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, + tr("*** Build failed - canceling Test Run ***"))); + return; + } + } + + // clear old log and output pane + m_xmlLog.clear(); + TestResultsPane::instance()->clearContents(); + + foreach (TestConfiguration *tc, m_selectedTests) { + QString cmd = tc->targetFile(); + QString workDir = tc->workingDirectory(); + QStringList args; + Utils::Environment env = tc->environment(); + + args << QLatin1String("-xml"); + if (tc->testCases().count()) + args << tc->testCases(); + + exec(cmd, args, workDir, env); + } + qDebug("test run finished"); +} + +void TestRunner::stopTestRun() +{ + +} + +/******************** XML line parser helper ********************/ + +static bool xmlStartsWith(const QString &code, const QString &start, QString &result) +{ + if (code.startsWith(start)) { + result = code.mid(start.length()); + result = result.left(result.indexOf(QLatin1Char('"'))); + result = result.left(result.indexOf(QLatin1String(""), index) - index); + return !result.isEmpty(); + } + return false; +} + +static bool xmlExtractTypeFileLine(const QString &code, const QString &tagStart, + ResultType &result, QString &file, int &line) +{ + if (code.startsWith(tagStart)) { + int start = code.indexOf(QLatin1String(" type=\"")) + 7; + result = TestResult::resultFromString( + code.mid(start, code.indexOf(QLatin1Char('"'), start) - start)); + start = code.indexOf(QLatin1String(" file=\"")) + 7; + file = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start); + start = code.indexOf(QLatin1String(" line=\"")) + 7; + line = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start).toInt(); + return true; + } + return false; +} + +/****************** XML line parser helper end ******************/ + +void TestRunner::processOutput() +{ + static QString className; + static QString testCase; + static QString dataTag; + static ResultType result = ResultType::UNKNOWN; + static QString description; + static QString file; + static int lineNumber = 0; + static QString duration; + static bool readingDescription = false; + static QString qtVersion; + static QString qtestVersion; + + while (m_runner.canReadLine()) { + // TODO Qt5 uses UTF-8 - while Qt4 uses ISO-8859-1 - could this be a problem? + QString line = QString::fromUtf8(m_runner.readLine()); + line = line.trimmed(); + m_xmlLog.append(line); + if (line.isEmpty() || line.startsWith(QLatin1String(""), dataTag)) + continue; + if (xmlCData(line, QLatin1String(""), description)) { + if (!line.endsWith(QLatin1String(""))) + readingDescription = true; + continue; + } + if (xmlExtractTypeFileLine(line, QLatin1String(""))) { + TestResult testResult(className, testCase, dataTag, result, description); + if (!file.isEmpty()) + file = QFileInfo(m_runner.workingDirectory(), file).canonicalFilePath(); + testResult.setFileName(file); + testResult.setLine(lineNumber); + TestResultsPane::instance()->addTestResult(testResult); + } + continue; + } + if (line == QLatin1String("") || line == QLatin1String("")) { + TestResult testResult(className, testCase, dataTag, result, description); + if (!file.isEmpty()) + file = QFileInfo(m_runner.workingDirectory(), file).canonicalFilePath(); + testResult.setFileName(file); + testResult.setLine(lineNumber); + TestResultsPane::instance()->addTestResult(testResult); + description = QString(); + } else if (line == QLatin1String("") && !duration.isEmpty()) { + TestResult testResult(className, testCase, QString(), ResultType::MESSAGE_INTERNAL, + tr("execution took %1ms").arg(duration)); + TestResultsPane::instance()->addTestResult(testResult); + } else if (line == QLatin1String("") && !duration.isEmpty()) { + TestResult testResult(className, QString(), QString(), ResultType::MESSAGE_INTERNAL, + tr("Test execution took %1ms").arg(duration)); + TestResultsPane::instance()->addTestResult(testResult); + } else if (readingDescription) { + if (line.endsWith(QLatin1String("]]>"))) { + description.append(QLatin1Char('\n')); + description.append(line.left(line.indexOf(QLatin1String("]]>")))); + readingDescription = false; + } else { + description.append(QLatin1Char('\n')); + description.append(line); + } + } else if (xmlStartsWith(line, QLatin1String(""), qtVersion)) { + TestResultsPane::instance()->addTestResult( + TestResult(QString(), QString(), QString(), ResultType::MESSAGE_INTERNAL, + tr("Qt Version: %1").arg(qtVersion))); + } else if (xmlStartsWith(line, QLatin1String(""), qtestVersion)) { + TestResultsPane::instance()->addTestResult( + TestResult(QString(), QString(), QString(), ResultType::MESSAGE_INTERNAL, + tr("QTest Version: %1").arg(qtestVersion))); + } else { +// qDebug() << "Unhandled line:" << line; // TODO remove + } + } +} + +void TestRunner::onRunnerFinished(int exitCode, QProcess::ExitStatus exitStatus) +{ + qDebug("runnerFinished"); +} + +void TestRunner::buildProject(ProjectExplorer::Project *project) +{ + m_building = true; + m_buildSucceeded = false; + ProjectExplorer::BuildManager *mgr = static_cast( + ProjectExplorer::BuildManager::instance()); + ProjectExplorer::ProjectExplorerPlugin *pep = ProjectExplorer::ProjectExplorerPlugin::instance(); + pep->buildProject(project); + connect(mgr, &ProjectExplorer::BuildManager::buildQueueFinished, + this, &TestRunner::buildFinished); +} + +void TestRunner::buildFinished(bool success) +{ + ProjectExplorer::BuildManager *mgr = static_cast( + ProjectExplorer::BuildManager::instance()); + disconnect(mgr, &ProjectExplorer::BuildManager::buildQueueFinished, + this, &TestRunner::buildFinished); + m_building = false; + m_buildSucceeded = success; +} + +static QString which(const QString &path, const QString &cmd) +{ + if (path.isEmpty() || cmd.isEmpty()) + return QString(); + + QStringList paths; +#ifdef Q_OS_WIN + paths = path.split(QLatin1Char(';')); +#else + paths = path.split(QLatin1Char(':')); +#endif + + foreach (const QString p, paths) { + QString fName = p + QDir::separator() + cmd; + QFileInfo fi(fName); + if (fi.exists() && fi.isExecutable()) + return fName; +#ifdef Q_OS_WIN + fi = QFileInfo(fName + QLatin1String(".exe")); + if (fi.exists()) + return fi.absoluteFilePath(); + fi = QFileInfo(fName + QLatin1String(".bat")); + if (fi.exists()) + return fi.absoluteFilePath(); + fi = QFileInfo(fName + QLatin1String(".cmd")); + if (fi.exists()) + return fi.absoluteFilePath(); +#endif + } + return QString(); +} + +bool TestRunner::exec(const QString &cmd, const QStringList &args, const QString &workingDir, + const Utils::Environment &env, int timeout) +{ + if (m_runner.state() != QProcess::NotRunning) { // kill the runner if it's running already + m_runner.kill(); + m_runner.waitForFinished(); + } + QString runCmd; + if (!QDir::toNativeSeparators(cmd).contains(QDir::separator())) { + if (env.hasKey(QLatin1String("PATH"))) + runCmd = which(env.value(QLatin1String("PATH")), cmd); + } else if (QFileInfo(cmd).exists()) { + runCmd = cmd; + } + + if (runCmd.isEmpty()) { + qDebug("Could not find cmd..."); + return false; + } + + m_runner.setWorkingDirectory(workingDir); + m_runner.setProcessEnvironment(env.toProcessEnvironment()); + QTime executionTimer; + + if (args.count()) { + m_runner.start(runCmd, args); + } else { + m_runner.start(runCmd); + } + + bool ok = m_runner.waitForStarted(); + executionTimer.start(); + if (ok) { + while (m_runner.state() == QProcess::Running && executionTimer.elapsed() < timeout) { + qApp->processEvents(); + } + } + if (ok && executionTimer.elapsed() < timeout) { + return m_runner.exitCode() == 0; + } else { + return false; + } +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testrunner.h b/plugins/autotest/testrunner.h new file mode 100644 index 00000000000..48f674716d2 --- /dev/null +++ b/plugins/autotest/testrunner.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTRUNNER_H +#define TESTRUNNER_H + +#include "testconfiguration.h" +#include "testresult.h" + +#include +#include + +namespace ProjectExplorer { +class Project; +} + +namespace Autotest { +namespace Internal { + +class TestRunner : public QObject +{ + Q_OBJECT + +public: + static TestRunner* instance(); + ~TestRunner(); + + void setSelectedTests(const QList &selected); + +signals: + +public slots: + void runTests(); + void stopTestRun(); + +private slots: + void processOutput(); + void onRunnerFinished(int exitCode, QProcess::ExitStatus exitStatus); + void buildProject(ProjectExplorer::Project *project); + void buildFinished(bool success); + +private: + explicit TestRunner(QObject *parent = 0); + bool exec(const QString &cmd, const QStringList &args, const QString &workingDir = QString(), + const Utils::Environment &env = Utils::Environment(), int timeout = 60000); + + QProcess m_runner; + QList m_selectedTests; + bool m_building; + bool m_buildSucceeded; + + QStringList m_xmlLog; // holds complete xml log of the last test run + +}; + +} // namespace Internal +} // namespace Autotest + +#endif // TESTRUNNER_H diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 88bc653d4ec..7cf8d2888d8 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -24,6 +24,16 @@ #include +#include +#include +#include +#include +#include +#include +#include + +#include + namespace Autotest { namespace Internal { @@ -115,6 +125,16 @@ int TestTreeModel::columnCount(const QModelIndex &) const return 1; } +static QIcon testTreeIcon(TestTreeItem::Type type) +{ + static QIcon icons[3] = { + QIcon(), + QIcon(QLatin1String(":/images/class.png")), + QIcon(QLatin1String(":/images/func.png")) + }; + return icons[type]; +} + QVariant TestTreeModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) @@ -138,15 +158,7 @@ QVariant TestTreeModel::data(const QModelIndex &index, int role) const case Qt::ToolTipRole: return item->filePath(); case Qt::DecorationRole: - switch(item->type()) { - case TestTreeItem::TEST_CLASS: - return QIcon(QLatin1String(":/images/class.png")); - case TestTreeItem::TEST_FUNCTION: - return QIcon(QLatin1String(":/images/func.png")); - case TestTreeItem::ROOT: - default: - return QVariant(); - } + return testTreeIcon(item->type()); case Qt::CheckStateRole: if (item->type() == TestTreeItem::ROOT) return QVariant(); @@ -234,6 +246,110 @@ bool TestTreeModel::hasTests() const return m_autoTestRootItem->childCount() > 0 /*|| m_quickTestRootItem->childCount() > 0*/; } +static void addProjectInformation(TestConfiguration *config, const QString &filePath) +{ + QString targetFile; + QString targetName; + QString workDir; + QString proFile; + Utils::Environment env; + ProjectExplorer::Project *project = 0; + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + QList projParts = cppMM->projectPart(filePath); + if (!projParts.empty()) { + proFile = projParts.at(0)->projectFile; + project = projParts.at(0)->project; // necessary to grab this here? or should this be the current active startup project anyway? + } + if (project) { + ProjectExplorer::Target *target = project->activeTarget(); + ProjectExplorer::BuildTargetInfoList appTargets = target->applicationTargets(); + foreach (ProjectExplorer::BuildTargetInfo bti, appTargets.list) { + if (bti.isValid() && bti.projectFilePath.toString() == proFile) { + targetFile = bti.targetFilePath.toString(); + targetName = bti.targetName; + break; + } + } + + QList rcs = target->runConfigurations(); + foreach (ProjectExplorer::RunConfiguration *rc, rcs) { + if (ProjectExplorer::LocalApplicationRunConfiguration *localRunConfiguration + = qobject_cast(rc)) { + if (localRunConfiguration->executable() == targetFile) { + workDir = localRunConfiguration->workingDirectory(); + QList aspects + = localRunConfiguration->extraAspects(); + foreach (ProjectExplorer::IRunConfigurationAspect *aspect, aspects) { + if (ProjectExplorer::EnvironmentAspect *asp + = qobject_cast(aspect)) { + env = asp->environment(); + break; + } + } + break; + } + } + } + } + config->setTargetFile(targetFile); + config->setTargetName(targetName); + config->setWorkingDirectory(workDir); + config->setProFile(proFile); + config->setEnvironment(env); + config->setProject(project); +} + +QList TestTreeModel::getAllTestCases() const +{ + QList result; + + int count = m_autoTestRootItem->childCount(); + for (int row = 0; row < count; ++row) { + TestTreeItem *child = m_autoTestRootItem->child(row); + + TestConfiguration *tc = new TestConfiguration(child->name(), QStringList()); + addProjectInformation(tc, child->filePath()); + result << tc; + } + return result; +} + +QList TestTreeModel::getSelectedTests() const +{ + QList result; + TestConfiguration *tc; + + int count = m_autoTestRootItem->childCount(); + for (int row = 0; row < count; ++row) { + TestTreeItem *child = m_autoTestRootItem->child(row); + + switch (child->checked()) { + case Qt::Unchecked: + continue; + case Qt::Checked: + tc = new TestConfiguration(child->name(), QStringList()); + addProjectInformation(tc, child->filePath()); + result << tc; + continue; + case Qt::PartiallyChecked: + default: + QString childName = child->name(); + int grandChildCount = child->childCount(); + QStringList testCases; + for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) { + const TestTreeItem *grandChild = child->child(grandChildRow); + if (grandChild->checked() == Qt::Checked) + testCases << grandChild->name(); + } + + tc = new TestConfiguration(childName, testCases); + addProjectInformation(tc, child->filePath()); + result << tc; + } + } + return result; +} + void TestTreeModel::modifyAutoTestSubtree(int row, TestTreeItem *newItem) { static QVector modificationRoles = QVector() << Qt::DisplayRole diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 9ec25f04762..040e1c912c0 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -19,6 +19,8 @@ #ifndef TESTTREEMODEL_H #define TESTTREEMODEL_H +#include "testconfiguration.h" + #include #include @@ -56,6 +58,8 @@ public: TestCodeParser *parser() const { return m_parser; } bool hasTests() const; + QList getAllTestCases() const; + QList getSelectedTests() const; signals: diff --git a/plugins/autotest/testtreeview.cpp b/plugins/autotest/testtreeview.cpp index 04b2ffb60fb..fc2fffe1c1d 100644 --- a/plugins/autotest/testtreeview.cpp +++ b/plugins/autotest/testtreeview.cpp @@ -18,12 +18,15 @@ #include "autotestconstants.h" #include "testcodeparser.h" +#include "testrunner.h" #include "testtreeitem.h" #include "testtreemodel.h" #include "testtreeview.h" #include +#include + #include #include @@ -48,12 +51,11 @@ TestTreeViewWidget::TestTreeViewWidget(QWidget *parent) : QVBoxLayout *layout = new QVBoxLayout; layout->setMargin(0); layout->setSpacing(0); - layout->addWidget(m_view); + layout->addWidget(Core::ItemViewFind::createSearchableWrapper(m_view)); setLayout(layout); TestCodeParser *parser = m_model->parser(); - ProjectExplorer::SessionManager *sm = static_cast( - ProjectExplorer::SessionManager::instance()); + ProjectExplorer::SessionManager *sm = ProjectExplorer::SessionManager::instance(); connect(sm, &ProjectExplorer::SessionManager::startupProjectChanged, parser, &TestCodeParser::updateTestTree); @@ -78,6 +80,8 @@ void TestTreeViewWidget::contextMenuEvent(QContextMenuEvent *event) // TODO remove? QAction *rescan = new QAction(tr("Rescan"), &menu); + connect(runAll, &QAction::triggered, this, &TestTreeViewWidget::onRunAllTriggered); + connect(runSelected, &QAction::triggered, this, &TestTreeViewWidget::onRunSelectedTriggered); connect(selectAll, &QAction::triggered, m_view, &TestTreeView::selectAll); connect(deselectAll, &QAction::triggered, m_view, &TestTreeView::deselectAll); connect(rescan, &QAction::triggered, @@ -103,11 +107,10 @@ QList TestTreeViewWidget::createToolButtons() { QList list; + m_sortAlphabetically = true; m_sort = new QToolButton(this); - m_sort->setIcon((QIcon(QLatin1String(":/images/sort.png")))); - m_sort->setToolTip(tr("Sort Alphabetically (not implemented yet)")); // TODO - m_sort->setCheckable(true); - m_sort->setChecked(true); + m_sort->setIcon((QIcon(QLatin1String(":/images/leafsort.png")))); + m_sort->setToolTip(tr("Sort Naturally (not implemented yet)")); QToolButton *expand = new QToolButton(this); expand->setIcon(QIcon(QLatin1String(":/images/expand.png"))); @@ -119,7 +122,7 @@ QList TestTreeViewWidget::createToolButtons() connect(expand, &QToolButton::clicked, m_view, &TestTreeView::expandAll); connect(collapse, &QToolButton::clicked, m_view, &TestTreeView::collapseAll); -// connect(m_sort, &QToolButton::toggled, m_view, &TestTreeView::onSortToggled); // TODO + connect(m_sort, &QToolButton::clicked, this, &TestTreeViewWidget::onSortClicked); list << m_sort << expand << collapse; return list; @@ -136,6 +139,33 @@ void TestTreeViewWidget::onItemActivated(const QModelIndex &index) } } +void TestTreeViewWidget::onRunAllTriggered() +{ + TestRunner *runner = TestRunner::instance(); + runner->setSelectedTests(m_model->getAllTestCases()); + runner->runTests(); +} + +void TestTreeViewWidget::onRunSelectedTriggered() +{ + TestRunner *runner = TestRunner::instance(); + runner->setSelectedTests(m_model->getSelectedTests()); + runner->runTests(); +} + +void TestTreeViewWidget::onSortClicked() +{ + if (m_sortAlphabetically) { + m_sort->setIcon((QIcon(QLatin1String(":/images/sort.png")))); + m_sort->setToolTip(tr("Sort Alphabetically")); + } else { + m_sort->setIcon((QIcon(QLatin1String(":/images/leafsort.png")))); + m_sort->setToolTip(tr("Sort Naturally (not implemented yet)")); + } + // TODO trigger the sorting change.. + m_sortAlphabetically = !m_sortAlphabetically; +} + TestViewFactory::TestViewFactory() { setDisplayName(tr("Tests")); @@ -145,10 +175,10 @@ TestViewFactory::TestViewFactory() Core::NavigationView TestViewFactory::createWidget() { - TestTreeViewWidget *treeView = new TestTreeViewWidget; + TestTreeViewWidget *treeViewWidget = new TestTreeViewWidget; Core::NavigationView view; - view.widget = treeView; - view.dockToolBarWidgets = treeView->createToolButtons(); + view.widget = treeViewWidget; + view.dockToolBarWidgets = treeViewWidget->createToolButtons(); return view; } diff --git a/plugins/autotest/testtreeview.h b/plugins/autotest/testtreeview.h index cb66fa12ccb..27e475f17c5 100644 --- a/plugins/autotest/testtreeview.h +++ b/plugins/autotest/testtreeview.h @@ -68,11 +68,15 @@ public slots: private slots: void onItemActivated(const QModelIndex &index); + void onRunAllTriggered(); + void onRunSelectedTriggered(); + void onSortClicked(); private: TestTreeModel *m_model; TestTreeView *m_view; QToolButton *m_sort; + bool m_sortAlphabetically; }; From eba497d92103072dd7dd88ee70d714e369e8063f Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 21 Oct 2014 13:10:37 +0200 Subject: [PATCH 003/200] Add filtering to test results --- plugins/autotest/testresult.h | 2 + plugins/autotest/testresultdelegate.cpp | 10 ++-- plugins/autotest/testresultmodel.cpp | 58 +++++++++++++++++++++- plugins/autotest/testresultmodel.h | 25 ++++++++++ plugins/autotest/testresultspane.cpp | 66 ++++++++++++++++++++----- plugins/autotest/testresultspane.h | 8 +++ plugins/autotest/testtreemodel.cpp | 25 +++++----- 7 files changed, 163 insertions(+), 31 deletions(-) diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index dc476916645..b8b6a2dd1a6 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -76,4 +76,6 @@ bool operator==(const TestResult &t1, const TestResult &t2); } // namespace Internal } // namespace Autotest +Q_DECLARE_METATYPE(Autotest::Internal::ResultType) + #endif // TESTRESULT_H diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp index 1f423d2e3a1..4231278276a 100644 --- a/plugins/autotest/testresultdelegate.cpp +++ b/plugins/autotest/testresultdelegate.cpp @@ -64,9 +64,10 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op painter->drawRect(opt.rect); painter->setPen(foreground); - TestResultModel *resultModel = static_cast(view->model()); + TestResultFilterModel *resultFilterModel = static_cast(view->model()); + TestResultModel *resultModel = static_cast(resultFilterModel->sourceModel()); LayoutPositions positions(opt, resultModel); - TestResult testResult = resultModel->testResult(index); + TestResult testResult = resultModel->testResult(resultFilterModel->mapToSource(index)); ResultType type = testResult.result(); QIcon icon = index.data(Qt::DecorationRole).value(); @@ -176,13 +177,14 @@ QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo QFontMetrics fm(opt.font); int fontHeight = fm.height(); - TestResultModel *resultModel = static_cast(view->model()); + TestResultFilterModel *resultFilterModel = static_cast(view->model()); + TestResultModel *resultModel = static_cast(resultFilterModel->sourceModel()); LayoutPositions positions(opt, resultModel); QSize s; s.setWidth(opt.rect.width()); if (selected) { - TestResult testResult = resultModel->testResult(index); + TestResult testResult = resultModel->testResult(resultFilterModel->mapToSource(index)); QString output; switch (testResult.result()) { diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index 1867987aa1f..9c7291d2e19 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -21,6 +21,7 @@ #include #include #include +#include namespace Autotest { namespace Internal { @@ -70,7 +71,7 @@ static QIcon testResultIcon(ResultType result) { QIcon(QLatin1String(":/images/debug.png")), QIcon(QLatin1String(":/images/warn.png")), QIcon(QLatin1String(":/images/fatal.png")), - }; + }; // provide an icon for unknown?? if (result < 0 || result >= MESSAGE_INTERNAL) return QIcon(); @@ -116,6 +117,9 @@ void TestResultModel::clearTestResults() return; beginRemoveRows(QModelIndex(), 0, m_testResults.size() - 1); m_testResults.clear(); + m_lastMaxWidthIndex = 0; + m_maxWidthOfFileName = 0; + m_widthOfLineNumber = 0; endRemoveRows(); } @@ -159,5 +163,57 @@ int TestResultModel::maxWidthOfLineNumber(const QFont &font) return m_widthOfLineNumber; } +/********************************** Filter Model **********************************/ + +TestResultFilterModel::TestResultFilterModel(TestResultModel *sourceModel, QObject *parent) + : QSortFilterProxyModel(parent), + m_sourceModel(sourceModel) +{ + setSourceModel(sourceModel); + enableAllResultTypes(); +} + +void TestResultFilterModel::enableAllResultTypes() +{ + m_enabled << ResultType::PASS << ResultType::FAIL << ResultType::EXPECTED_FAIL + << ResultType::UNEXPECTED_PASS << ResultType::SKIP << ResultType::MESSAGE_DEBUG + << ResultType::MESSAGE_WARN << ResultType::MESSAGE_INTERNAL + << ResultType::MESSAGE_FATAL << ResultType::UNKNOWN; + invalidateFilter(); +} + +void TestResultFilterModel::toggleTestResultType(ResultType type) +{ + if (m_enabled.contains(type)) { + m_enabled.remove(type); + } else { + m_enabled.insert(type); + } + invalidateFilter(); +} + +void TestResultFilterModel::clearTestResults() +{ + m_sourceModel->clearTestResults(); +} + +bool TestResultFilterModel::hasResults() +{ + return rowCount(QModelIndex()); +} + +TestResult TestResultFilterModel::testResult(const QModelIndex &index) const +{ + return m_sourceModel->testResult(mapToSource(index)); +} + +bool TestResultFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + QModelIndex index = m_sourceModel->index(sourceRow, 0, sourceParent); + if (!index.isValid()) + return false; + return m_enabled.contains(m_sourceModel->testResult(index).result()); +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testresultmodel.h b/plugins/autotest/testresultmodel.h index fa358205546..c0a71fe44ba 100644 --- a/plugins/autotest/testresultmodel.h +++ b/plugins/autotest/testresultmodel.h @@ -22,7 +22,9 @@ #include "testresult.h" #include +#include #include +#include namespace Autotest { namespace Internal { @@ -48,6 +50,9 @@ public: int maxWidthOfFileName(const QFont &font); int maxWidthOfLineNumber(const QFont &font); + void enableAllResultTypes(); + void toggleTestResultType(ResultType type); + signals: public slots: @@ -60,6 +65,26 @@ private: QFont m_measurementFont; }; +class TestResultFilterModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + TestResultFilterModel(TestResultModel *sourceModel, QObject *parent = 0); + + void enableAllResultTypes(); + void toggleTestResultType(ResultType type); + void clearTestResults(); + bool hasResults(); + TestResult testResult(const QModelIndex &index) const; + +protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; + +private: + TestResultModel *m_sourceModel; + QSet m_enabled; +}; + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 100de73e58b..244b775f93c 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -22,12 +22,14 @@ #include "testrunner.h" #include "testtreemodel.h" +#include #include #include #include +#include #include namespace Autotest { @@ -39,7 +41,9 @@ TestResultsPane::TestResultsPane(QObject *parent) : { m_listView = new Utils::ListView; m_model = new TestResultModel(this); - m_listView->setModel(m_model); + m_filterModel = new TestResultFilterModel(m_model, this); + m_filterModel->setDynamicSortFilter(true); + m_listView->setModel(m_filterModel); TestResultDelegate *trd = new TestResultDelegate(this); m_listView->setItemDelegate(trd); @@ -61,6 +65,17 @@ void TestResultsPane::createToolButtons() m_runSelected->setIcon(QIcon(QLatin1String(":/images/runselected.png"))); m_runSelected->setToolTip(tr("Run Selected Tests")); connect(m_runSelected, &QToolButton::clicked, this, &TestResultsPane::onRunSelectedTriggered); + + m_filterButton = new QToolButton(m_listView); + m_filterButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_FILTER))); + m_filterButton->setToolTip(tr("Filter Test Results")); + m_filterButton->setProperty("noArrow", true); + m_filterButton->setAutoRaise(true); + m_filterButton->setPopupMode(QToolButton::InstantPopup); + m_filterMenu = new QMenu(m_filterButton); + initializeFilterMenu(); + connect(m_filterMenu, &QMenu::triggered, this, &TestResultsPane::filterMenuTriggered); + m_filterButton->setMenu(m_filterMenu); } static TestResultsPane *m_instance = 0; @@ -99,7 +114,7 @@ QWidget *TestResultsPane::outputWidget(QWidget *parent) QList TestResultsPane::toolBarWidgets() const { - return QList() << m_runAll << m_runSelected; // add filter as well + return QList() << m_runAll << m_runSelected << m_filterButton; } QString TestResultsPane::displayName() const @@ -114,7 +129,7 @@ int TestResultsPane::priorityInStatusBar() const void TestResultsPane::clearContents() { - m_model->clearTestResults(); + m_filterModel->clearTestResults(); navigateStateChanged(); } @@ -143,12 +158,12 @@ bool TestResultsPane::canNavigate() const bool TestResultsPane::canNext() const { - return m_model->hasResults(); + return m_filterModel->hasResults(); } bool TestResultsPane::canPrevious() const { - return m_model->hasResults(); + return m_filterModel->hasResults(); } void TestResultsPane::goToNext() @@ -159,11 +174,11 @@ void TestResultsPane::goToNext() QModelIndex currentIndex = m_listView->currentIndex(); if (currentIndex.isValid()) { int row = currentIndex.row() + 1; - if (row == m_model->rowCount(QModelIndex())) + if (row == m_filterModel->rowCount(QModelIndex())) row = 0; - currentIndex = m_model->index(row, 0, QModelIndex()); + currentIndex = m_filterModel->index(row, 0, QModelIndex()); } else { - currentIndex = m_model->index(0, 0, QModelIndex()); + currentIndex = m_filterModel->index(0, 0, QModelIndex()); } m_listView->setCurrentIndex(currentIndex); onItemActivated(currentIndex); @@ -178,10 +193,10 @@ void TestResultsPane::goToPrev() if (currentIndex.isValid()) { int row = currentIndex.row() - 1; if (row < 0) - row = m_model->rowCount(QModelIndex()) - 1; - currentIndex = m_model->index(row, 0, QModelIndex()); + row = m_filterModel->rowCount(QModelIndex()) - 1; + currentIndex = m_filterModel->index(row, 0, QModelIndex()); } else { - currentIndex = m_model->index(m_model->rowCount(QModelIndex()) - 1, 0, QModelIndex()); + currentIndex = m_filterModel->index(m_filterModel->rowCount(QModelIndex()) - 1, 0, QModelIndex()); } m_listView->setCurrentIndex(currentIndex); onItemActivated(currentIndex); @@ -192,7 +207,7 @@ void TestResultsPane::onItemActivated(const QModelIndex &index) if (!index.isValid()) return; - TestResult tr = m_model->testResult(index); + TestResult tr = m_filterModel->testResult(index); if (!tr.fileName().isEmpty()) Core::EditorManager::openEditorAt(tr.fileName(), tr.line(), 0); } @@ -209,7 +224,34 @@ void TestResultsPane::onRunSelectedTriggered() TestRunner *runner = TestRunner::instance(); runner->setSelectedTests(TestTreeModel::instance()->getSelectedTests()); runner->runTests(); +} +void TestResultsPane::initializeFilterMenu() +{ + QMap textAndType; + textAndType.clear(); + textAndType.insert(ResultType::PASS, QLatin1String("Pass")); + textAndType.insert(ResultType::FAIL, QLatin1String("Fail")); + textAndType.insert(ResultType::EXPECTED_FAIL, QLatin1String("Expected Fail")); + textAndType.insert(ResultType::UNEXPECTED_PASS, QLatin1String("Unexpected Pass")); + textAndType.insert(ResultType::SKIP, QLatin1String("Skip")); + textAndType.insert(ResultType::MESSAGE_DEBUG, QLatin1String("Debug Messages")); + textAndType.insert(ResultType::MESSAGE_WARN, QLatin1String("Warning Messages")); + textAndType.insert(ResultType::MESSAGE_INTERNAL, QLatin1String("Internal Messages")); + foreach (ResultType result, textAndType.keys()) { + QAction *action = new QAction(m_filterMenu); + action->setText(textAndType.value(result)); + action->setCheckable(true); + action->setChecked(true); + action->setData(result); + m_filterMenu->addAction(action); + } +} + +void TestResultsPane::filterMenuTriggered(QAction *action) +{ + m_filterModel->toggleTestResultType(static_cast(action->data().value())); + navigateStateChanged(); } } // namespace Internal diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h index 28aff09103d..86936223ac1 100644 --- a/plugins/autotest/testresultspane.h +++ b/plugins/autotest/testresultspane.h @@ -22,7 +22,9 @@ #include QT_BEGIN_NAMESPACE +class QAction; class QModelIndex; +class QMenu; class QToolButton; QT_END_NAMESPACE @@ -39,6 +41,7 @@ namespace Internal { class TestResult; class TestResultModel; +class TestResultFilterModel; class TestResultsPane : public Core::IOutputPane { @@ -73,6 +76,8 @@ private slots: void onItemActivated(const QModelIndex &index); void onRunAllTriggered(); void onRunSelectedTriggered(); + void initializeFilterMenu(); + void filterMenuTriggered(QAction *action); private: explicit TestResultsPane(QObject *parent = 0); @@ -80,9 +85,12 @@ private: Utils::ListView *m_listView; TestResultModel *m_model; + TestResultFilterModel *m_filterModel; Core::IContext *m_context; QToolButton *m_runAll; QToolButton *m_runSelected; + QToolButton *m_filterButton; + QMenu *m_filterMenu; }; } // namespace Internal diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 7cf8d2888d8..fe9a091b554 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -20,9 +20,7 @@ #include "testtreeitem.h" #include "testtreemodel.h" -#include - -#include +#include #include #include @@ -32,7 +30,11 @@ #include #include -#include +#include + +#include + +#include namespace Autotest { namespace Internal { @@ -276,16 +278,11 @@ static void addProjectInformation(TestConfiguration *config, const QString &file if (ProjectExplorer::LocalApplicationRunConfiguration *localRunConfiguration = qobject_cast(rc)) { if (localRunConfiguration->executable() == targetFile) { - workDir = localRunConfiguration->workingDirectory(); - QList aspects - = localRunConfiguration->extraAspects(); - foreach (ProjectExplorer::IRunConfigurationAspect *aspect, aspects) { - if (ProjectExplorer::EnvironmentAspect *asp - = qobject_cast(aspect)) { - env = asp->environment(); - break; - } - } + workDir = Utils::FileUtils::normalizePathName( + localRunConfiguration->workingDirectory()); + ProjectExplorer::EnvironmentAspect *envAsp + = localRunConfiguration->extraAspect(); + env = envAsp->environment(); break; } } From eca8e2faba320331a4ae5ad0e5ec3c9c55559144 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 28 Oct 2014 13:02:34 +0100 Subject: [PATCH 004/200] Add license validation with LicenseChecker plugin --- plugins/autotest/autotest_dependencies.pri | 3 ++- plugins/autotest/autotestplugin.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/plugins/autotest/autotest_dependencies.pri b/plugins/autotest/autotest_dependencies.pri index af150efd0c4..c5d76107a00 100644 --- a/plugins/autotest/autotest_dependencies.pri +++ b/plugins/autotest/autotest_dependencies.pri @@ -3,7 +3,8 @@ QTC_PLUGIN_NAME = AutoTest QTC_PLUGIN_DEPENDS += \ coreplugin \ projectexplorer \ - cpptools + cpptools \ + licensechecker QTC_LIB_DEPENDS += \ cplusplus \ diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index 7dcb029d905..065b561f5ff 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -30,6 +30,10 @@ #include #include +#include + +#include + #include #include #include @@ -66,6 +70,15 @@ bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorStri Q_UNUSED(arguments) Q_UNUSED(errorString) + LicenseChecker::LicenseCheckerPlugin *licenseChecker + = ExtensionSystem::PluginManager::getObject(); + + if (!licenseChecker || !licenseChecker->hasValidLicense()) { + qWarning() << "Invalid license, disabling Qt Creator Enterprise Auto Test Add-on."; + return true; + } else if (!licenseChecker->enterpriseFeatures()) + return true; + QAction *action = new QAction(tr("Autotest action"), this); Core::Command *cmd = Core::ActionManager::registerAction(action, Constants::ACTION_ID, Core::Context(Core::Constants::C_GLOBAL)); From 345b4de47a82916296e60643442e84cd737a2f8b Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 28 Oct 2014 15:57:13 +0100 Subject: [PATCH 005/200] Rework the parsing and fixing detection of changes Additionally * fixed some deletion of pointers * const correctness * small refactorings for readability * better separation of responsibilities --- plugins/autotest/testcodeparser.cpp | 188 +++++++++++++++++----------- plugins/autotest/testcodeparser.h | 2 + plugins/autotest/testinfo.h | 3 + plugins/autotest/testrunner.cpp | 4 +- plugins/autotest/testtreemodel.cpp | 55 +++++--- plugins/autotest/testtreemodel.h | 7 +- plugins/autotest/testvisitor.cpp | 55 +++++++- plugins/autotest/testvisitor.h | 21 ++++ 8 files changed, 240 insertions(+), 95 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index f1cd6872d05..71e76ee5d19 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -30,6 +30,8 @@ #include +#include + namespace Autotest { namespace Internal { @@ -40,17 +42,18 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent) { } +TestCodeParser::~TestCodeParser() +{ + clearMaps(); +} + void TestCodeParser::updateTestTree() { qDebug("updating TestTreeModel"); - m_model->beginResetModel(); - qDeleteAll(m_cppDocMap); - m_cppDocMap.clear(); - QModelIndex autoTestRootIndex = m_model->index(0, 0); - TestTreeItem *autoTestRootItem = static_cast(autoTestRootIndex.internalPointer()); - autoTestRootItem->removeChildren(); - m_model->endResetModel(); - ProjectExplorer::SessionManager *session = ProjectExplorer::SessionManager::instance(); + + clearMaps(); + m_model->removeAllAutoTests(); + const ProjectExplorer::SessionManager *session = ProjectExplorer::SessionManager::instance(); if (!session || !session->hasProjects()) return; @@ -62,12 +65,30 @@ void TestCodeParser::updateTestTree() /****** scan for QTest related stuff helpers ******/ +static QByteArray getFileContent(QString filePath) +{ + QByteArray fileContent; + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + CppTools::WorkingCopy wc = cppMM->workingCopy(); + if (wc.contains(filePath)) { + fileContent = wc.source(filePath); + } else { + QString error; + const QTextCodec *codec = Core::EditorManager::defaultTextCodec(); + if (Utils::TextFileFormat::readFileUTF8(filePath, codec, &fileContent, &error) + != Utils::TextFileFormat::ReadSuccess) { + qDebug() << "Failed to read file" << filePath << ":" << error; + } + } + return fileContent; +} + static bool includesQtTest(const CPlusPlus::Document::Ptr &doc, const CppTools::CppModelManager *cppMM) { - QList includes = doc->resolvedIncludes(); + const QList includes = doc->resolvedIncludes(); - foreach (CPlusPlus::Document::Include inc, includes) { + foreach (const CPlusPlus::Document::Include inc, includes) { // TODO this short cut works only for #include // bad, as there could be much more different approaches if (inc.unresolvedFileName() == QLatin1String("QtTest") @@ -78,8 +99,8 @@ static bool includesQtTest(const CPlusPlus::Document::Ptr &doc, if (cppMM) { CPlusPlus::Snapshot snapshot = cppMM->snapshot(); - QSet includes = snapshot.allIncludesForDocument(doc->fileName()); - foreach (QString include, includes) { + const QSet allIncludes = snapshot.allIncludesForDocument(doc->fileName()); + foreach (const QString include, allIncludes) { if (include.endsWith(QLatin1String("QtTest/qtest.h"))) { return true; } @@ -91,11 +112,9 @@ static bool includesQtTest(const CPlusPlus::Document::Ptr &doc, static bool qtTestLibDefined(const CppTools::CppModelManager *cppMM, const QString &fileName) { - QList parts = cppMM->projectPart(fileName); - if (parts.size() > 0) { - QByteArray projDefines = parts.at(0)->projectDefines; - return projDefines.contains("#define QT_TESTLIB_LIB 1"); - } + const QList parts = cppMM->projectPart(fileName); + if (parts.size() > 0) + return parts.at(0)->projectDefines.contains("#define QT_TESTLIB_LIB 1"); return false; } @@ -103,33 +122,16 @@ static QString testClass(const CPlusPlus::Document::Ptr &doc) { static QByteArray qtTestMacros[] = {"QTEST_MAIN", "QTEST_APPLESS_MAIN", "QTEST_GUILESS_MAIN"}; QString tC; - QList macros = doc->macroUses(); + const QList macros = doc->macroUses(); - foreach (CPlusPlus::Document::MacroUse macro, macros) { + foreach (const CPlusPlus::Document::MacroUse macro, macros) { if (!macro.isFunctionLike()) continue; - QByteArray name = macro.macro().name(); + const QByteArray name = macro.macro().name(); if (name == qtTestMacros[0] || name == qtTestMacros[1] || name == qtTestMacros[2]) { CPlusPlus::Document::Block arg = macro.arguments().at(0); - CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); - - // TODO high costs....?! - CppTools::WorkingCopy wc = cppMM->workingCopy(); - if (wc.contains(doc->fileName())) { - QByteArray src = wc.source(doc->fileName()); - tC = QLatin1String(src.mid(arg.bytesBegin(), arg.bytesEnd() - arg.bytesBegin())); - } else { - QFile current(doc->fileName()); - if (current.exists() && current.open(QFile::ReadOnly)) { - CPlusPlus::Document::Block arg = macro.arguments().at(0); - if (current.seek(arg.bytesBegin())) { - QByteArray res = current.read(arg.bytesEnd() - arg.bytesBegin()); - if (!res.isEmpty()) - tC = QLatin1String(res); - } - current.close(); - } - } + tC = QLatin1String(getFileContent(doc->fileName()).mid(arg.bytesBegin(), + arg.bytesEnd() - arg.bytesBegin())); break; } } @@ -141,53 +143,64 @@ static QString testClass(const CPlusPlus::Document::Ptr &doc) void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) { const QString file = doc->fileName(); - CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); if (includesQtTest(doc, cppMM) && qtTestLibDefined(cppMM, file)) { - QString tc = testClass(doc); + QString tc(testClass(doc)); if (tc.isEmpty()) { // one might have used an approach without macros or defined own macros - QString src = QLatin1String(doc->utf8Source()); // does not work anymore - src is always "" - if (src.contains(QLatin1String("QTest::qExec"))) { - qDebug() << "Src\n===============\n" << src << "\n=============\n"; - // TODO extract the class name by using the AST - using regex is too problematic as this - // does not take comments and typedefs or whatever into account.... - qDebug() << "Currently not supported approach... (self-defined macro / QTest::qExec() call/...)"; - } - } else { - QModelIndex autoTestRootIndex = m_model->index(0, 0); + const CPlusPlus::Snapshot snapshot = cppMM->snapshot(); + const QByteArray fileContent = getFileContent(file); + doc = snapshot.preprocessedDocument(fileContent, file); + doc->check(); + CPlusPlus::AST *ast = doc->translationUnit()->ast(); + TestAstVisitor astVisitor(doc); + astVisitor.accept(ast); + tc = astVisitor.className(); + } + if (!tc.isEmpty()) { + // construct the new/modified TestTreeItem + const QModelIndex autoTestRootIndex = m_model->index(0, 0); TestTreeItem *autoTestRootItem = static_cast(autoTestRootIndex.internalPointer()); TestTreeItem *ttItem = new TestTreeItem(tc, file, TestTreeItem::TEST_CLASS, autoTestRootItem); + QString declFileName; CPlusPlus::TypeOfExpression toe; toe.init(doc, cppMM->snapshot()); CPlusPlus::Document::Ptr declaringDoc = doc; - QList toeItems = toe(tc.toUtf8(), doc->globalNamespace()); + const QList toeItems = toe(tc.toUtf8(), doc->globalNamespace()); if (toeItems.size()) { CPlusPlus::Class *toeClass = toeItems.first().declaration()->asClass(); - QString declFileName = QLatin1String(toeClass->fileId()->chars(), - toeClass->fileId()->size()); + declFileName = QLatin1String(toeClass->fileId()->chars(), + toeClass->fileId()->size()); declaringDoc = cppMM->snapshot().document(declFileName); ttItem->setFilePath(declFileName); ttItem->setLine(toeClass->line()); ttItem->setColumn(toeClass->column() - 1); } - if (declaringDoc.isNull()) + if (declaringDoc.isNull()) { + delete ttItem; return; + } TestVisitor myVisitor(tc); myVisitor.accept(declaringDoc->globalNamespace()); - QMap privSlots = myVisitor.privateSlots(); + const QMap privSlots = myVisitor.privateSlots(); foreach (const QString privS, privSlots.keys()) { - TestCodeLocation location = privSlots.value(privS); + const TestCodeLocation location = privSlots.value(privS); TestTreeItem *ttSub = new TestTreeItem(privS, location.m_fileName, TestTreeItem::TEST_FUNCTION, ttItem); ttSub->setLine(location.m_line); ttSub->setColumn(location.m_column); ttItem->appendChild(ttSub); } + + // TODO refactoring? + // update model and internal map + TestInfo *info; + int count; if (m_cppDocMap.contains(file)) { - TestInfo *info = m_cppDocMap[file]; - int count = autoTestRootItem->childCount(); + info = m_cppDocMap[file]; + count = autoTestRootItem->childCount(); for (int i = 0; i < count; ++i) { TestTreeItem *currentItem = autoTestRootItem->child(i); if (currentItem->filePath() == file) { @@ -199,13 +212,40 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) break; } } + info = m_cppDocMap[declFileName]; + count = autoTestRootItem->childCount(); + for (int i = 0; i < count; ++i) { + TestTreeItem *currentItem = autoTestRootItem->child(i); + if (currentItem->filePath() == declFileName) { + m_model->modifyAutoTestSubtree(i, ttItem); + TestInfo *ti = new TestInfo(tc, privSlots.keys(), + doc->revision(), + doc->editorRevision()); + ti->setReferencingFile(file); + m_cppDocMap.insert(declFileName, ti); + delete info; + break; + } + } delete ttItem; } else { - m_model->beginInsertRows(autoTestRootIndex, autoTestRootItem->childCount(), autoTestRootItem->childCount()); - autoTestRootItem->appendChild(ttItem); - m_model->endInsertRows(); + m_model->addAutoTest(ttItem); m_cppDocMap.insert(file, new TestInfo(tc, privSlots.keys(), doc->revision(), doc->editorRevision())); + TestInfo *ti = new TestInfo(tc, privSlots.keys(), + doc->revision(), doc->editorRevision()); + ti->setReferencingFile(file); + m_cppDocMap.insert(declFileName, ti); + } + } + } else { + // could not find the class to test, but QTest is included and QT_TESTLIB_LIB defined + // maybe file is only a referenced file + if (m_cppDocMap.contains(file)) { + const TestInfo *info = m_cppDocMap[file]; + CPlusPlus::Snapshot snapshot = cppMM->snapshot(); + if (snapshot.contains(info->referencingFile())) { + checkDocumentForTestCode(snapshot.find(info->referencingFile()).value()); } } } @@ -215,24 +255,22 @@ void TestCodeParser::onDocumentUpdated(CPlusPlus::Document::Ptr doc) { if (!m_currentProject) return; - QString fileName = doc->fileName(); - if (!m_cppDocMap.contains(fileName)) { - if (!m_currentProject->files(ProjectExplorer::Project::AllFiles).contains(fileName)) { - return; - } - } else { + const QString fileName = doc->fileName(); + if (m_cppDocMap.contains(fileName)) { if (m_cppDocMap[fileName]->revision() == doc->revision() && m_cppDocMap[fileName]->editorRevision() == doc->editorRevision()) { qDebug("Skipped due revision equality"); // added to verify if this ever happens.. return; } + } else if (!m_currentProject->files(ProjectExplorer::Project::AllFiles).contains(fileName)) { + return; } checkDocumentForTestCode(doc); } void TestCodeParser::removeFiles(const QStringList &files) { - foreach (QString file, files) { + foreach (const QString file, files) { if (m_cppDocMap.contains(file)) { TestInfo *info = m_cppDocMap.value(file); m_cppDocMap.remove(file); @@ -244,11 +282,11 @@ void TestCodeParser::removeFiles(const QStringList &files) void TestCodeParser::scanForTests() { - QStringList list = m_currentProject->files(ProjectExplorer::Project::AllFiles); + const QStringList list = m_currentProject->files(ProjectExplorer::Project::AllFiles); CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); CPlusPlus::Snapshot snapshot = cppMM->snapshot(); - foreach (QString file, list) { + foreach (const QString file, list) { if (snapshot.contains(file)) { CPlusPlus::Document::Ptr doc = snapshot.find(file).value(); checkDocumentForTestCode(doc); @@ -256,5 +294,15 @@ void TestCodeParser::scanForTests() } } +void TestCodeParser::clearMaps() +{ + QMap::iterator it = m_cppDocMap.begin(); + while (it != m_cppDocMap.end()) { + delete it.value(); + ++it; + } + m_cppDocMap.clear(); +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 1eaed0b063a..aeeb2d69724 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -39,6 +39,7 @@ class TestCodeParser : public QObject Q_OBJECT public: explicit TestCodeParser(TestTreeModel *parent = 0); + virtual ~TestCodeParser(); signals: @@ -51,6 +52,7 @@ public slots: private: void scanForTests(); + void clearMaps(); TestTreeModel *m_model; QMap m_cppDocMap; diff --git a/plugins/autotest/testinfo.h b/plugins/autotest/testinfo.h index bfb7ef33c5e..91b6be99960 100644 --- a/plugins/autotest/testinfo.h +++ b/plugins/autotest/testinfo.h @@ -39,12 +39,15 @@ public: void setRevision(unsigned revision) { m_revision = revision; } unsigned editorRevision() const { return m_editorRevision; } void setEditorRevision(unsigned editorRevision) { m_editorRevision = editorRevision; } + const QString referencingFile() const { return m_referencingFile; } + void setReferencingFile(const QString &refFile) {m_referencingFile = refFile; } private: QString m_className; QStringList m_functions; unsigned m_revision; unsigned m_editorRevision; + QString m_referencingFile; }; } // namespace Internal diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 5a1f41baefb..fe73cd91e8b 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -86,7 +86,9 @@ void TestRunner::runTests() ProjectExplorer::Internal::ProjectExplorerSettings pes = pep->projectExplorerSettings(); if (pes.buildBeforeDeploy) { if (!project->hasActiveBuildSettings()) { - qDebug() << "no active build settings...???"; // let it configure? + TestResultsPane::instance()->addTestResult( + TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, + tr("*** Project is not configured - canceling Test Run ***"))); return; } buildProject(project); diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index fe9a091b554..a0aff69744b 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -263,29 +263,30 @@ static void addProjectInformation(TestConfiguration *config, const QString &file project = projParts.at(0)->project; // necessary to grab this here? or should this be the current active startup project anyway? } if (project) { - ProjectExplorer::Target *target = project->activeTarget(); - ProjectExplorer::BuildTargetInfoList appTargets = target->applicationTargets(); - foreach (ProjectExplorer::BuildTargetInfo bti, appTargets.list) { - if (bti.isValid() && bti.projectFilePath.toString() == proFile) { - targetFile = bti.targetFilePath.toString(); - targetName = bti.targetName; - break; - } - } - - QList rcs = target->runConfigurations(); - foreach (ProjectExplorer::RunConfiguration *rc, rcs) { - if (ProjectExplorer::LocalApplicationRunConfiguration *localRunConfiguration - = qobject_cast(rc)) { - if (localRunConfiguration->executable() == targetFile) { - workDir = Utils::FileUtils::normalizePathName( - localRunConfiguration->workingDirectory()); - ProjectExplorer::EnvironmentAspect *envAsp - = localRunConfiguration->extraAspect(); - env = envAsp->environment(); + if (auto target = project->activeTarget()) { + ProjectExplorer::BuildTargetInfoList appTargets = target->applicationTargets(); + foreach (ProjectExplorer::BuildTargetInfo bti, appTargets.list) { + if (bti.isValid() && bti.projectFilePath.toString() == proFile) { + targetFile = bti.targetFilePath.toString(); + targetName = bti.targetName; break; } } + + QList rcs = target->runConfigurations(); + foreach (ProjectExplorer::RunConfiguration *rc, rcs) { + if (ProjectExplorer::LocalApplicationRunConfiguration *localRunConfiguration + = qobject_cast(rc)) { + if (localRunConfiguration->executable() == targetFile) { + workDir = Utils::FileUtils::normalizePathName( + localRunConfiguration->workingDirectory()); + ProjectExplorer::EnvironmentAspect *envAsp + = localRunConfiguration->extraAspect(); + env = envAsp->environment(); + break; + } + } + } } } config->setTargetFile(targetFile); @@ -438,5 +439,19 @@ void TestTreeModel::removeAutoTestSubtreeByFilePath(const QString &file) } } +void TestTreeModel::addAutoTest(TestTreeItem *newItem) +{ + beginInsertRows(index(0, 0), m_autoTestRootItem->childCount(), m_autoTestRootItem->childCount()); + m_autoTestRootItem->appendChild(newItem); + endInsertRows(); +} + +void TestTreeModel::removeAllAutoTests() +{ + beginResetModel(); + m_autoTestRootItem->removeChildren(); + endResetModel(); +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 040e1c912c0..9e70016b342 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -61,13 +61,15 @@ public: QList getAllTestCases() const; QList getSelectedTests() const; + void modifyAutoTestSubtree(int row, TestTreeItem *newItem); + void removeAutoTestSubtreeByFilePath(const QString &file); + void addAutoTest(TestTreeItem *newItem); + void removeAllAutoTests(); signals: public slots: private: - void modifyAutoTestSubtree(int row, TestTreeItem *newItem); - void removeAutoTestSubtreeByFilePath(const QString &file); explicit TestTreeModel(QObject *parent = 0); TestTreeItem *m_rootItem; @@ -75,7 +77,6 @@ private: // TestTreeItem *m_quickTestRootItem; TestCodeParser *m_parser; - friend class TestCodeParser; }; } // namespace Internal diff --git a/plugins/autotest/testvisitor.cpp b/plugins/autotest/testvisitor.cpp index 4f83c9d55b3..e1c4fda65b3 100644 --- a/plugins/autotest/testvisitor.cpp +++ b/plugins/autotest/testvisitor.cpp @@ -18,9 +18,13 @@ #include "testvisitor.h" +#include #include #include #include +#include + +#include #include @@ -57,7 +61,7 @@ bool TestVisitor::visit(CPlusPlus::Class *symbol) if (auto func = type->asFunctionType()) { if (func->isSlot() && member->isPrivate()) { - QString name = o.prettyName(func->name()); + const QString name = o.prettyName(func->name()); if (!ignoredFunctions.contains(name) && !name.endsWith(QLatin1String("_data"))) { TestCodeLocation location; location.m_fileName = QLatin1String(member->fileName()); @@ -71,5 +75,54 @@ bool TestVisitor::visit(CPlusPlus::Class *symbol) return true; } +TestAstVisitor::TestAstVisitor(CPlusPlus::Document::Ptr doc) + : ASTVisitor(doc->translationUnit()), + m_currentDoc(doc) +{ +} + +TestAstVisitor::~TestAstVisitor() +{ +} + +bool TestAstVisitor::visit(CPlusPlus::CallAST *ast) +{ + if (!m_currentScope || m_currentDoc.isNull()) + return false; + + if (auto expressionAST = ast->base_expression) { + if (auto idExpressionAST = expressionAST->asIdExpression()) { + if (auto qualifiedNameAST = idExpressionAST->name->asQualifiedName()) { + const CPlusPlus::Overview o; + const QString prettyName = o.prettyName(qualifiedNameAST->name); + if (prettyName == QLatin1String("QTest::qExec")) { + if (auto expressionListAST = ast->expression_list) { + // first argument is the one we need + if (auto argumentExpressionAST = expressionListAST->value) { + CPlusPlus::TypeOfExpression toe; + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + toe.init(m_currentDoc, cppMM->snapshot()); + QList toeItems + = toe(argumentExpressionAST, m_currentDoc, m_currentScope); + + if (toeItems.size()) { + if (auto pointerType = toeItems.first().type()->asPointerType()) + m_className = o.prettyType(pointerType->elementType()); + } + } + } + } + } + } + } + return false; +} + +bool TestAstVisitor::visit(CPlusPlus::CompoundStatementAST *ast) +{ + m_currentScope = ast->symbol->asScope(); + return true; +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testvisitor.h b/plugins/autotest/testvisitor.h index c3fafac6a96..04076cf80c5 100644 --- a/plugins/autotest/testvisitor.h +++ b/plugins/autotest/testvisitor.h @@ -19,6 +19,9 @@ #ifndef TESTVISITOR_H #define TESTVISITOR_H +#include +#include +#include #include #include @@ -48,6 +51,24 @@ private: QMap m_privSlots; }; +class TestAstVisitor : public CPlusPlus::ASTVisitor +{ +public: + TestAstVisitor(CPlusPlus::Document::Ptr doc); + virtual ~TestAstVisitor(); + + bool visit(CPlusPlus::CallAST *ast); + bool visit(CPlusPlus::CompoundStatementAST *ast); + + QString className() const { return m_className; } + +private: + QString m_className; + CPlusPlus::Scope *m_currentScope; + CPlusPlus::Document::Ptr m_currentDoc; + +}; + } // namespace Internal } // namespace Autotest From 431d15bd0caa70588c7118ef8c0b32850d08ab82 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 3 Nov 2014 08:30:22 +0100 Subject: [PATCH 006/200] Add stop button and minor preparation for progress bar --- plugins/autotest/autotest.qrc | 1 + plugins/autotest/images/stop.png | Bin 0 -> 314 bytes plugins/autotest/testconfiguration.cpp | 6 +++++- plugins/autotest/testconfiguration.h | 4 +++- plugins/autotest/testresultspane.cpp | 26 ++++++++++++++++++++++++- plugins/autotest/testresultspane.h | 3 +++ plugins/autotest/testrunner.cpp | 15 +++++++++++++- plugins/autotest/testrunner.h | 2 ++ plugins/autotest/testtreemodel.cpp | 5 +++-- 9 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 plugins/autotest/images/stop.png diff --git a/plugins/autotest/autotest.qrc b/plugins/autotest/autotest.qrc index b4b47f100f6..fe59718a584 100644 --- a/plugins/autotest/autotest.qrc +++ b/plugins/autotest/autotest.qrc @@ -16,5 +16,6 @@ images/xpass.png images/run.png images/runselected.png + images/stop.png diff --git a/plugins/autotest/images/stop.png b/plugins/autotest/images/stop.png new file mode 100644 index 0000000000000000000000000000000000000000..1063d089985794a49542c61f78e8d8514f7f9607 GIT binary patch literal 314 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7BuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztFx>HUaSW-rwPdm*SF?eDtNPK+QMXFZUrb#px48N% zo19~aK#Yc{j@V?i%S%j@%vN?WpKSSXfBqQ<4y8lW3ce)zpKx7vnCseZCArSJMw0`Z zUrSB3IH~2gkN;AGMRC&H%2?*}#SdH=n=aiKvs)y%selectionModel(), &QItemSelectionModel::currentChanged, trd, &TestResultDelegate::currentChanged); + connect(TestRunner::instance(), &TestRunner::testRunStarted, + this, &TestResultsPane::onTestRunStarted); + connect(TestRunner::instance(), &TestRunner::testRunFinished, + this, &TestResultsPane::onTestRunFinished); } void TestResultsPane::createToolButtons() @@ -66,6 +70,12 @@ void TestResultsPane::createToolButtons() m_runSelected->setToolTip(tr("Run Selected Tests")); connect(m_runSelected, &QToolButton::clicked, this, &TestResultsPane::onRunSelectedTriggered); + m_stopTestRun = new QToolButton(m_listView); + m_stopTestRun->setIcon(QIcon(QLatin1String(":/images/stop.png"))); + m_stopTestRun->setToolTip(tr("Stop Test Run")); + m_stopTestRun->setEnabled(false); + connect(m_stopTestRun, &QToolButton::clicked, TestRunner::instance(), &TestRunner::stopTestRun); + m_filterButton = new QToolButton(m_listView); m_filterButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_FILTER))); m_filterButton->setToolTip(tr("Filter Test Results")); @@ -114,7 +124,7 @@ QWidget *TestResultsPane::outputWidget(QWidget *parent) QList TestResultsPane::toolBarWidgets() const { - return QList() << m_runAll << m_runSelected << m_filterButton; + return QList() << m_runAll << m_runSelected << m_stopTestRun << m_filterButton; } QString TestResultsPane::displayName() const @@ -254,5 +264,19 @@ void TestResultsPane::filterMenuTriggered(QAction *action) navigateStateChanged(); } +void TestResultsPane::onTestRunStarted() +{ + m_stopTestRun->setEnabled(true); + m_runAll->setEnabled(false); + m_runSelected->setEnabled(false); +} + +void TestResultsPane::onTestRunFinished() +{ + m_stopTestRun->setEnabled(false); + m_runAll->setEnabled(true); + m_runSelected->setEnabled(true); +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h index 86936223ac1..6f3df33e5c9 100644 --- a/plugins/autotest/testresultspane.h +++ b/plugins/autotest/testresultspane.h @@ -82,6 +82,8 @@ private slots: private: explicit TestResultsPane(QObject *parent = 0); void createToolButtons(); + void onTestRunStarted(); + void onTestRunFinished(); Utils::ListView *m_listView; TestResultModel *m_model; @@ -89,6 +91,7 @@ private: Core::IContext *m_context; QToolButton *m_runAll; QToolButton *m_runSelected; + QToolButton *m_stopTestRun; QToolButton *m_filterButton; QMenu *m_filterMenu; }; diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index fe73cd91e8b..ded6fab9f1e 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -104,10 +104,16 @@ void TestRunner::runTests() } } + int testCaseCount = 0; + foreach (const TestConfiguration *config, m_selectedTests) + testCaseCount += config->testCaseCount(); + // clear old log and output pane m_xmlLog.clear(); TestResultsPane::instance()->clearContents(); + emit testRunStarted(); + foreach (TestConfiguration *tc, m_selectedTests) { QString cmd = tc->targetFile(); QString workDir = tc->workingDirectory(); @@ -121,11 +127,18 @@ void TestRunner::runTests() exec(cmd, args, workDir, env); } qDebug("test run finished"); + emit testRunFinished(); } void TestRunner::stopTestRun() { - + if (m_runner.state() != QProcess::NotRunning) { + m_runner.kill(); + m_runner.waitForFinished(); + TestResultsPane::instance()->addTestResult( + TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, + tr("*** Test Run canceled by user ***"))); + } } /******************** XML line parser helper ********************/ diff --git a/plugins/autotest/testrunner.h b/plugins/autotest/testrunner.h index 48f674716d2..6ed530d05cb 100644 --- a/plugins/autotest/testrunner.h +++ b/plugins/autotest/testrunner.h @@ -43,6 +43,8 @@ public: void setSelectedTests(const QList &selected); signals: + void testRunStarted(); + void testRunFinished(); public slots: void runTests(); diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index a0aff69744b..39b42ba5b97 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -305,7 +305,8 @@ QList TestTreeModel::getAllTestCases() const for (int row = 0; row < count; ++row) { TestTreeItem *child = m_autoTestRootItem->child(row); - TestConfiguration *tc = new TestConfiguration(child->name(), QStringList()); + TestConfiguration *tc = new TestConfiguration(child->name(), QStringList(), + child->childCount()); addProjectInformation(tc, child->filePath()); result << tc; } @@ -325,7 +326,7 @@ QList TestTreeModel::getSelectedTests() const case Qt::Unchecked: continue; case Qt::Checked: - tc = new TestConfiguration(child->name(), QStringList()); + tc = new TestConfiguration(child->name(), QStringList(), child->childCount()); addProjectInformation(tc, child->filePath()); result << tc; continue; From d5913658b2d0f2bd04a5522e32bc8496414cb0ed Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 4 Nov 2014 12:35:00 +0100 Subject: [PATCH 007/200] Perform test execution in separate thread and add progress bar --- plugins/autotest/autotestconstants.h | 1 + plugins/autotest/testrunner.cpp | 358 ++++++++++++++------------- plugins/autotest/testrunner.h | 7 - 3 files changed, 191 insertions(+), 175 deletions(-) diff --git a/plugins/autotest/autotestconstants.h b/plugins/autotest/autotestconstants.h index df3e26be11b..3cfc770d45d 100644 --- a/plugins/autotest/autotestconstants.h +++ b/plugins/autotest/autotestconstants.h @@ -26,6 +26,7 @@ const char ACTION_ID[] = "AutoTest.Action"; const char MENU_ID[] = "AutoTest.Menu"; const char AUTOTEST_ID[] = "AutoTest.ATP"; const char AUTOTEST_CONTEXT[] = "Auto Tests"; +const char TASK_INDEX[] = "AutoTest.Task.Index"; } // namespace Autotest } // namespace Constants diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index ded6fab9f1e..eae9d4c58a7 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -16,22 +16,32 @@ ** ****************************************************************************/ +#include "autotestconstants.h" #include "testresultspane.h" #include "testrunner.h" #include // REMOVE +#include +#include + #include #include #include #include +#include + +#include +#include #include namespace Autotest { namespace Internal { -static TestRunner* m_instance = 0; +static TestRunner *m_instance = 0; +static QProcess *m_runner = 0; +static QFutureInterface *m_currentFuture = 0; TestRunner *TestRunner::instance() { @@ -44,13 +54,6 @@ TestRunner::TestRunner(QObject *parent) : QObject(parent), m_building(false) { - m_runner.setReadChannelMode(QProcess::MergedChannels); - m_runner.setReadChannel(QProcess::StandardOutput); - - connect(&m_runner, &QProcess::readyReadStandardOutput, - this, &TestRunner::processOutput, Qt::DirectConnection); - connect(&m_runner, SIGNAL(finished(int,QProcess::ExitStatus)), - this, SLOT(onRunnerFinished(int,QProcess::ExitStatus)), Qt::DirectConnection); } TestRunner::~TestRunner() @@ -58,6 +61,8 @@ TestRunner::~TestRunner() qDeleteAll(m_selectedTests); m_selectedTests.clear(); m_instance = 0; + if (m_runner) + delete m_runner; } void TestRunner::setSelectedTests(const QList &selected) @@ -67,80 +72,6 @@ void TestRunner::setSelectedTests(const QList &selected) m_selectedTests = selected; } -void TestRunner::runTests() -{ - if (m_selectedTests.empty()) { - TestResultsPane::instance()->addTestResult( - TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, - tr("*** No tests selected - canceling Test Run ***"))); - return; - } - - ProjectExplorer::Project *project = m_selectedTests.at(0)->project(); - - if (!project) {// add a warning or info to output? possible at all? - return; - } - - ProjectExplorer::ProjectExplorerPlugin *pep = ProjectExplorer::ProjectExplorerPlugin::instance(); - ProjectExplorer::Internal::ProjectExplorerSettings pes = pep->projectExplorerSettings(); - if (pes.buildBeforeDeploy) { - if (!project->hasActiveBuildSettings()) { - TestResultsPane::instance()->addTestResult( - TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, - tr("*** Project is not configured - canceling Test Run ***"))); - return; - } - buildProject(project); - while (m_building) { - qApp->processEvents(); - } - - if (!m_buildSucceeded) { - TestResultsPane::instance()->addTestResult( - TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, - tr("*** Build failed - canceling Test Run ***"))); - return; - } - } - - int testCaseCount = 0; - foreach (const TestConfiguration *config, m_selectedTests) - testCaseCount += config->testCaseCount(); - - // clear old log and output pane - m_xmlLog.clear(); - TestResultsPane::instance()->clearContents(); - - emit testRunStarted(); - - foreach (TestConfiguration *tc, m_selectedTests) { - QString cmd = tc->targetFile(); - QString workDir = tc->workingDirectory(); - QStringList args; - Utils::Environment env = tc->environment(); - - args << QLatin1String("-xml"); - if (tc->testCases().count()) - args << tc->testCases(); - - exec(cmd, args, workDir, env); - } - qDebug("test run finished"); - emit testRunFinished(); -} - -void TestRunner::stopTestRun() -{ - if (m_runner.state() != QProcess::NotRunning) { - m_runner.kill(); - m_runner.waitForFinished(); - TestResultsPane::instance()->addTestResult( - TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, - tr("*** Test Run canceled by user ***"))); - } -} - /******************** XML line parser helper ********************/ static bool xmlStartsWith(const QString &code, const QString &start, QString &result) @@ -182,8 +113,10 @@ static bool xmlExtractTypeFileLine(const QString &code, const QString &tagStart, /****************** XML line parser helper end ******************/ -void TestRunner::processOutput() +void processOutput() { + if (!m_runner) + return; static QString className; static QString testCase; static QString dataTag; @@ -196,11 +129,9 @@ void TestRunner::processOutput() static QString qtVersion; static QString qtestVersion; - while (m_runner.canReadLine()) { + while (m_runner->canReadLine()) { // TODO Qt5 uses UTF-8 - while Qt4 uses ISO-8859-1 - could this be a problem? - QString line = QString::fromUtf8(m_runner.readLine()); - line = line.trimmed(); - m_xmlLog.append(line); + const QString line = QString::fromUtf8(m_runner->readLine()).trimmed(); if (line.isEmpty() || line.startsWith(QLatin1String(""))) { TestResult testResult(className, testCase, dataTag, result, description); if (!file.isEmpty()) - file = QFileInfo(m_runner.workingDirectory(), file).canonicalFilePath(); + file = QFileInfo(m_runner->workingDirectory(), file).canonicalFilePath(); testResult.setFileName(file); testResult.setLine(lineNumber); TestResultsPane::instance()->addTestResult(testResult); @@ -243,18 +174,19 @@ void TestRunner::processOutput() if (line == QLatin1String("") || line == QLatin1String("")) { TestResult testResult(className, testCase, dataTag, result, description); if (!file.isEmpty()) - file = QFileInfo(m_runner.workingDirectory(), file).canonicalFilePath(); + file = QFileInfo(m_runner->workingDirectory(), file).canonicalFilePath(); testResult.setFileName(file); testResult.setLine(lineNumber); TestResultsPane::instance()->addTestResult(testResult); description = QString(); } else if (line == QLatin1String("") && !duration.isEmpty()) { TestResult testResult(className, testCase, QString(), ResultType::MESSAGE_INTERNAL, - tr("execution took %1ms").arg(duration)); + QObject::tr("execution took %1ms").arg(duration)); TestResultsPane::instance()->addTestResult(testResult); + m_currentFuture->setProgressValue(m_currentFuture->progressValue() + 1); } else if (line == QLatin1String("") && !duration.isEmpty()) { TestResult testResult(className, QString(), QString(), ResultType::MESSAGE_INTERNAL, - tr("Test execution took %1ms").arg(duration)); + QObject::tr("Test execution took %1ms").arg(duration)); TestResultsPane::instance()->addTestResult(testResult); } else if (readingDescription) { if (line.endsWith(QLatin1String("]]>"))) { @@ -268,20 +200,180 @@ void TestRunner::processOutput() } else if (xmlStartsWith(line, QLatin1String(""), qtVersion)) { TestResultsPane::instance()->addTestResult( TestResult(QString(), QString(), QString(), ResultType::MESSAGE_INTERNAL, - tr("Qt Version: %1").arg(qtVersion))); + QObject::tr("Qt Version: %1").arg(qtVersion))); } else if (xmlStartsWith(line, QLatin1String(""), qtestVersion)) { TestResultsPane::instance()->addTestResult( TestResult(QString(), QString(), QString(), ResultType::MESSAGE_INTERNAL, - tr("QTest Version: %1").arg(qtestVersion))); + QObject::tr("QTest Version: %1").arg(qtestVersion))); } else { // qDebug() << "Unhandled line:" << line; // TODO remove } } } -void TestRunner::onRunnerFinished(int exitCode, QProcess::ExitStatus exitStatus) +static QString which(const QString &path, const QString &cmd) { - qDebug("runnerFinished"); + if (path.isEmpty() || cmd.isEmpty()) + return QString(); + + QStringList paths; +#ifdef Q_OS_WIN + paths = path.split(QLatin1Char(';')); +#else + paths = path.split(QLatin1Char(':')); +#endif + + foreach (const QString p, paths) { + const QString fName = p + QDir::separator() + cmd; + QFileInfo fi(fName); + if (fi.exists() && fi.isExecutable()) + return fName; +#ifdef Q_OS_WIN + fi = QFileInfo(fName + QLatin1String(".exe")); + if (fi.exists()) + return fi.absoluteFilePath(); + fi = QFileInfo(fName + QLatin1String(".bat")); + if (fi.exists()) + return fi.absoluteFilePath(); + fi = QFileInfo(fName + QLatin1String(".cmd")); + if (fi.exists()) + return fi.absoluteFilePath(); +#endif + } + return QString(); +} + +bool performExec(const QString &cmd, const QStringList &args, const QString &workingDir, + const Utils::Environment &env, int timeout = 60000) +{ + QString runCmd; + if (!QDir::toNativeSeparators(cmd).contains(QDir::separator())) { + if (env.hasKey(QLatin1String("PATH"))) + runCmd = which(env.value(QLatin1String("PATH")), cmd); + } else if (QFileInfo(cmd).exists()) { + runCmd = cmd; + } + + if (runCmd.isEmpty()) { + TestResultsPane::instance()->addTestResult( + TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, + QObject::tr("*** Could not find command '%1' ***").arg(cmd))); + return false; + } + + m_runner->setWorkingDirectory(workingDir); + m_runner->setProcessEnvironment(env.toProcessEnvironment()); + QTime executionTimer; + + if (args.count()) { + m_runner->start(runCmd, args); + } else { + m_runner->start(runCmd); + } + + bool ok = m_runner->waitForStarted(); + executionTimer.start(); + if (ok) { + while (m_runner->state() == QProcess::Running && executionTimer.elapsed() < timeout) { + if (m_currentFuture->isCanceled()) { + m_runner->kill(); + m_runner->waitForFinished(); + TestResultsPane::instance()->addTestResult( + TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, + QObject::tr("*** Test Run canceled by user ***"))); + } + qApp->processEvents(); + } + } + if (ok && executionTimer.elapsed() < timeout) { + return m_runner->exitCode() == 0; + } else { + return false; + } +} + +void performTestRun(QFutureInterface &future, const QList selectedTests) +{ + int testCaseCount = 0; + foreach (const TestConfiguration *config, selectedTests) + testCaseCount += config->testCaseCount(); + + m_currentFuture = &future; + m_runner = new QProcess; + m_runner->setReadChannelMode(QProcess::MergedChannels); + m_runner->setReadChannel(QProcess::StandardOutput); + + QObject::connect(m_runner, &QProcess::readyReadStandardOutput, &processOutput); + + future.setProgressRange(0, testCaseCount); + future.setProgressValue(0); + + foreach (const TestConfiguration *tc, selectedTests) { + if (future.isCanceled()) + break; + QString cmd = tc->targetFile(); + QString workDir = tc->workingDirectory(); + QStringList args; + Utils::Environment env = tc->environment(); + + args << QLatin1String("-xml"); + if (tc->testCases().count()) + args << tc->testCases(); + + performExec(cmd, args, workDir, env); + } + future.setProgressValue(testCaseCount); + + delete m_runner; + m_runner = 0; + m_currentFuture = 0; +} + +void TestRunner::runTests() +{ + if (m_selectedTests.empty()) { + TestResultsPane::instance()->addTestResult( + TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, + tr("*** No tests selected - canceling Test Run ***"))); + return; + } + + ProjectExplorer::Project *project = m_selectedTests.at(0)->project(); + + if (!project) // add a warning or info to output? possible at all? + return; + + ProjectExplorer::ProjectExplorerPlugin *pep = ProjectExplorer::ProjectExplorerPlugin::instance(); + ProjectExplorer::Internal::ProjectExplorerSettings pes = pep->projectExplorerSettings(); + if (pes.buildBeforeDeploy) { + if (!project->hasActiveBuildSettings()) { + TestResultsPane::instance()->addTestResult( + TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, + tr("*** Project is not configured - canceling Test Run ***"))); + return; + } + buildProject(project); + while (m_building) { + qApp->processEvents(); + } + + if (!m_buildSucceeded) { + TestResultsPane::instance()->addTestResult( + TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, + tr("*** Build failed - canceling Test Run ***"))); + return; + } + } + + // clear old log and output pane + TestResultsPane::instance()->clearContents(); + + emit testRunStarted(); + QFuture future = QtConcurrent::run(&performTestRun , m_selectedTests); + Core::FutureProgress *progress = Core::ProgressManager::addTask(future, tr("Running Tests"), + Autotest::Constants::TASK_INDEX); + connect(progress, &Core::FutureProgress::finished, + TestRunner::instance(), &TestRunner::testRunFinished); } void TestRunner::buildProject(ProjectExplorer::Project *project) @@ -306,80 +398,10 @@ void TestRunner::buildFinished(bool success) m_buildSucceeded = success; } -static QString which(const QString &path, const QString &cmd) +void TestRunner::stopTestRun() { - if (path.isEmpty() || cmd.isEmpty()) - return QString(); - - QStringList paths; -#ifdef Q_OS_WIN - paths = path.split(QLatin1Char(';')); -#else - paths = path.split(QLatin1Char(':')); -#endif - - foreach (const QString p, paths) { - QString fName = p + QDir::separator() + cmd; - QFileInfo fi(fName); - if (fi.exists() && fi.isExecutable()) - return fName; -#ifdef Q_OS_WIN - fi = QFileInfo(fName + QLatin1String(".exe")); - if (fi.exists()) - return fi.absoluteFilePath(); - fi = QFileInfo(fName + QLatin1String(".bat")); - if (fi.exists()) - return fi.absoluteFilePath(); - fi = QFileInfo(fName + QLatin1String(".cmd")); - if (fi.exists()) - return fi.absoluteFilePath(); -#endif - } - return QString(); -} - -bool TestRunner::exec(const QString &cmd, const QStringList &args, const QString &workingDir, - const Utils::Environment &env, int timeout) -{ - if (m_runner.state() != QProcess::NotRunning) { // kill the runner if it's running already - m_runner.kill(); - m_runner.waitForFinished(); - } - QString runCmd; - if (!QDir::toNativeSeparators(cmd).contains(QDir::separator())) { - if (env.hasKey(QLatin1String("PATH"))) - runCmd = which(env.value(QLatin1String("PATH")), cmd); - } else if (QFileInfo(cmd).exists()) { - runCmd = cmd; - } - - if (runCmd.isEmpty()) { - qDebug("Could not find cmd..."); - return false; - } - - m_runner.setWorkingDirectory(workingDir); - m_runner.setProcessEnvironment(env.toProcessEnvironment()); - QTime executionTimer; - - if (args.count()) { - m_runner.start(runCmd, args); - } else { - m_runner.start(runCmd); - } - - bool ok = m_runner.waitForStarted(); - executionTimer.start(); - if (ok) { - while (m_runner.state() == QProcess::Running && executionTimer.elapsed() < timeout) { - qApp->processEvents(); - } - } - if (ok && executionTimer.elapsed() < timeout) { - return m_runner.exitCode() == 0; - } else { - return false; - } + if (m_runner && m_runner->state() != QProcess::NotRunning && m_currentFuture) + m_currentFuture->cancel(); } } // namespace Internal diff --git a/plugins/autotest/testrunner.h b/plugins/autotest/testrunner.h index 6ed530d05cb..1a725eada77 100644 --- a/plugins/autotest/testrunner.h +++ b/plugins/autotest/testrunner.h @@ -51,23 +51,16 @@ public slots: void stopTestRun(); private slots: - void processOutput(); - void onRunnerFinished(int exitCode, QProcess::ExitStatus exitStatus); void buildProject(ProjectExplorer::Project *project); void buildFinished(bool success); private: explicit TestRunner(QObject *parent = 0); - bool exec(const QString &cmd, const QStringList &args, const QString &workingDir = QString(), - const Utils::Environment &env = Utils::Environment(), int timeout = 60000); - QProcess m_runner; QList m_selectedTests; bool m_building; bool m_buildSucceeded; - QStringList m_xmlLog; // holds complete xml log of the last test run - }; } // namespace Internal From 87e5cf87e1dce9d46a6ffd9906f6be47f6941fbd Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 4 Nov 2014 13:42:38 +0100 Subject: [PATCH 008/200] Enable 'Run *' buttons only if tests are available --- plugins/autotest/testresultspane.cpp | 9 +++++++++ plugins/autotest/testresultspane.h | 1 + plugins/autotest/testrunner.cpp | 7 +++---- plugins/autotest/testtreemodel.cpp | 4 ++++ plugins/autotest/testtreemodel.h | 1 + 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 5deb34803e0..bb641d264a4 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -56,6 +56,8 @@ TestResultsPane::TestResultsPane(QObject *parent) : this, &TestResultsPane::onTestRunStarted); connect(TestRunner::instance(), &TestRunner::testRunFinished, this, &TestResultsPane::onTestRunFinished); + connect(TestTreeModel::instance(), &TestTreeModel::testTreeModelChanged, + this, &TestResultsPane::onTestTreeModelChanged); } void TestResultsPane::createToolButtons() @@ -278,5 +280,12 @@ void TestResultsPane::onTestRunFinished() m_runSelected->setEnabled(true); } +void TestResultsPane::onTestTreeModelChanged() +{ + bool enable = TestTreeModel::instance()->hasTests(); + m_runAll->setEnabled(enable); + m_runSelected->setEnabled(enable); +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h index 6f3df33e5c9..af8222e512e 100644 --- a/plugins/autotest/testresultspane.h +++ b/plugins/autotest/testresultspane.h @@ -84,6 +84,7 @@ private: void createToolButtons(); void onTestRunStarted(); void onTestRunFinished(); + void onTestTreeModelChanged(); Utils::ListView *m_listView; TestResultModel *m_model; diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index eae9d4c58a7..4591f94081f 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -331,6 +331,9 @@ void performTestRun(QFutureInterface &future, const QListclearContents(); + if (m_selectedTests.empty()) { TestResultsPane::instance()->addTestResult( TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, @@ -339,7 +342,6 @@ void TestRunner::runTests() } ProjectExplorer::Project *project = m_selectedTests.at(0)->project(); - if (!project) // add a warning or info to output? possible at all? return; @@ -365,9 +367,6 @@ void TestRunner::runTests() } } - // clear old log and output pane - TestResultsPane::instance()->clearContents(); - emit testRunStarted(); QFuture future = QtConcurrent::run(&performTestRun , m_selectedTests); Core::FutureProgress *progress = Core::ProgressManager::addTask(future, tr("Running Tests"), diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 39b42ba5b97..214afb110a4 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -424,6 +424,7 @@ void TestTreeModel::modifyAutoTestSubtree(int row, TestTreeItem *newItem) } // remove rest of the items removeRows(newChildCount, childCount - newChildCount, toBeModifiedIndex); } + emit testTreeModelChanged(); } void TestTreeModel::removeAutoTestSubtreeByFilePath(const QString &file) @@ -438,6 +439,7 @@ void TestTreeModel::removeAutoTestSubtreeByFilePath(const QString &file) break; } } + emit testTreeModelChanged(); } void TestTreeModel::addAutoTest(TestTreeItem *newItem) @@ -445,6 +447,7 @@ void TestTreeModel::addAutoTest(TestTreeItem *newItem) beginInsertRows(index(0, 0), m_autoTestRootItem->childCount(), m_autoTestRootItem->childCount()); m_autoTestRootItem->appendChild(newItem); endInsertRows(); + emit testTreeModelChanged(); } void TestTreeModel::removeAllAutoTests() @@ -452,6 +455,7 @@ void TestTreeModel::removeAllAutoTests() beginResetModel(); m_autoTestRootItem->removeChildren(); endResetModel(); + emit testTreeModelChanged(); } } // namespace Internal diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 9e70016b342..0a07ef0e3a1 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -66,6 +66,7 @@ public: void addAutoTest(TestTreeItem *newItem); void removeAllAutoTests(); signals: + void testTreeModelChanged(); public slots: From 8bb03409353be640a18b58dd80e1bb67f96f13fe Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 4 Nov 2014 14:16:22 +0100 Subject: [PATCH 009/200] Enable filter items on availability If there are items inside the results pane that match the filter item filtering for these kind of results will be enabled. --- plugins/autotest/testresultmodel.cpp | 2 ++ plugins/autotest/testresultmodel.h | 2 ++ plugins/autotest/testresultspane.cpp | 10 +++++++++- plugins/autotest/testresultspane.h | 3 ++- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index 9c7291d2e19..ed03bae173f 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -109,6 +109,7 @@ void TestResultModel::addTestResult(const TestResult &testResult) beginInsertRows(QModelIndex(), m_testResults.size(), m_testResults.size()); m_testResults.append(testResult); endInsertRows(); + m_availableResultTypes.insert(testResult.result()); } void TestResultModel::clearTestResults() @@ -121,6 +122,7 @@ void TestResultModel::clearTestResults() m_maxWidthOfFileName = 0; m_widthOfLineNumber = 0; endRemoveRows(); + m_availableResultTypes.clear(); } TestResult TestResultModel::testResult(const QModelIndex &index) const diff --git a/plugins/autotest/testresultmodel.h b/plugins/autotest/testresultmodel.h index c0a71fe44ba..c803d113b6f 100644 --- a/plugins/autotest/testresultmodel.h +++ b/plugins/autotest/testresultmodel.h @@ -52,6 +52,7 @@ public: void enableAllResultTypes(); void toggleTestResultType(ResultType type); + bool hasResultType(ResultType type) { return m_availableResultTypes.contains(type); } signals: @@ -63,6 +64,7 @@ private: int m_maxWidthOfFileName; int m_lastMaxWidthIndex; QFont m_measurementFont; + QSet m_availableResultTypes; }; class TestResultFilterModel : public QSortFilterProxyModel diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index bb641d264a4..eee9fc93408 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -86,6 +86,7 @@ void TestResultsPane::createToolButtons() m_filterButton->setPopupMode(QToolButton::InstantPopup); m_filterMenu = new QMenu(m_filterButton); initializeFilterMenu(); + connect(m_filterMenu, &QMenu::aboutToShow, this, &TestResultsPane::updateFilterMenu); connect(m_filterMenu, &QMenu::triggered, this, &TestResultsPane::filterMenuTriggered); m_filterButton->setMenu(m_filterMenu); } @@ -241,7 +242,6 @@ void TestResultsPane::onRunSelectedTriggered() void TestResultsPane::initializeFilterMenu() { QMap textAndType; - textAndType.clear(); textAndType.insert(ResultType::PASS, QLatin1String("Pass")); textAndType.insert(ResultType::FAIL, QLatin1String("Fail")); textAndType.insert(ResultType::EXPECTED_FAIL, QLatin1String("Expected Fail")); @@ -260,6 +260,14 @@ void TestResultsPane::initializeFilterMenu() } } +void TestResultsPane::updateFilterMenu() +{ + foreach (QAction *action, m_filterMenu->actions()) { + action->setEnabled(m_model->hasResultType( + static_cast(action->data().value()))); + } +} + void TestResultsPane::filterMenuTriggered(QAction *action) { m_filterModel->toggleTestResultType(static_cast(action->data().value())); diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h index af8222e512e..58363cbb044 100644 --- a/plugins/autotest/testresultspane.h +++ b/plugins/autotest/testresultspane.h @@ -76,11 +76,12 @@ private slots: void onItemActivated(const QModelIndex &index); void onRunAllTriggered(); void onRunSelectedTriggered(); - void initializeFilterMenu(); + void updateFilterMenu(); void filterMenuTriggered(QAction *action); private: explicit TestResultsPane(QObject *parent = 0); + void initializeFilterMenu(); void createToolButtons(); void onTestRunStarted(); void onTestRunFinished(); From 8e4181c3afbb9ca5354dbed72138a6685bca6313 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 5 Nov 2014 10:34:18 +0100 Subject: [PATCH 010/200] Use TestInfo as object instead of pointer No need for having this more complicated than necessary. --- plugins/autotest/testcodeparser.cpp | 60 ++++++++++++----------------- plugins/autotest/testcodeparser.h | 2 +- plugins/autotest/testinfo.h | 3 +- 3 files changed, 28 insertions(+), 37 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 71e76ee5d19..61c0e03933e 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -171,12 +171,14 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) const QList toeItems = toe(tc.toUtf8(), doc->globalNamespace()); if (toeItems.size()) { CPlusPlus::Class *toeClass = toeItems.first().declaration()->asClass(); - declFileName = QLatin1String(toeClass->fileId()->chars(), - toeClass->fileId()->size()); - declaringDoc = cppMM->snapshot().document(declFileName); - ttItem->setFilePath(declFileName); - ttItem->setLine(toeClass->line()); - ttItem->setColumn(toeClass->column() - 1); + if (toeClass) { + declFileName = QLatin1String(toeClass->fileId()->chars(), + toeClass->fileId()->size()); + declaringDoc = cppMM->snapshot().document(declFileName); + ttItem->setFilePath(declFileName); + ttItem->setLine(toeClass->line()); + ttItem->setColumn(toeClass->column() - 1); + } } if (declaringDoc.isNull()) { delete ttItem; @@ -196,45 +198,40 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) // TODO refactoring? // update model and internal map - TestInfo *info; + TestInfo info; int count; if (m_cppDocMap.contains(file)) { - info = m_cppDocMap[file]; + info = m_cppDocMap.value(file); count = autoTestRootItem->childCount(); for (int i = 0; i < count; ++i) { TestTreeItem *currentItem = autoTestRootItem->child(i); if (currentItem->filePath() == file) { m_model->modifyAutoTestSubtree(i, ttItem); - m_cppDocMap.insert(file, new TestInfo(tc, privSlots.keys(), - doc->revision(), - doc->editorRevision())); - delete info; + m_cppDocMap.insert(file, TestInfo(tc, privSlots.keys(), + doc->revision(), + doc->editorRevision())); break; } } - info = m_cppDocMap[declFileName]; + info = m_cppDocMap.value(declFileName); count = autoTestRootItem->childCount(); for (int i = 0; i < count; ++i) { TestTreeItem *currentItem = autoTestRootItem->child(i); if (currentItem->filePath() == declFileName) { m_model->modifyAutoTestSubtree(i, ttItem); - TestInfo *ti = new TestInfo(tc, privSlots.keys(), - doc->revision(), - doc->editorRevision()); - ti->setReferencingFile(file); + TestInfo ti(tc, privSlots.keys(), doc->revision(), doc->editorRevision()); + ti.setReferencingFile(file); m_cppDocMap.insert(declFileName, ti); - delete info; break; } } delete ttItem; } else { m_model->addAutoTest(ttItem); - m_cppDocMap.insert(file, new TestInfo(tc, privSlots.keys(), - doc->revision(), doc->editorRevision())); - TestInfo *ti = new TestInfo(tc, privSlots.keys(), - doc->revision(), doc->editorRevision()); - ti->setReferencingFile(file); + m_cppDocMap.insert(file, TestInfo(tc, privSlots.keys(), doc->revision(), + doc->editorRevision())); + TestInfo ti(tc, privSlots.keys(), doc->revision(), doc->editorRevision()); + ti.setReferencingFile(file); m_cppDocMap.insert(declFileName, ti); } } @@ -242,10 +239,10 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) // could not find the class to test, but QTest is included and QT_TESTLIB_LIB defined // maybe file is only a referenced file if (m_cppDocMap.contains(file)) { - const TestInfo *info = m_cppDocMap[file]; + const TestInfo info = m_cppDocMap[file]; CPlusPlus::Snapshot snapshot = cppMM->snapshot(); - if (snapshot.contains(info->referencingFile())) { - checkDocumentForTestCode(snapshot.find(info->referencingFile()).value()); + if (snapshot.contains(info.referencingFile())) { + checkDocumentForTestCode(snapshot.find(info.referencingFile()).value()); } } } @@ -257,8 +254,8 @@ void TestCodeParser::onDocumentUpdated(CPlusPlus::Document::Ptr doc) return; const QString fileName = doc->fileName(); if (m_cppDocMap.contains(fileName)) { - if (m_cppDocMap[fileName]->revision() == doc->revision() - && m_cppDocMap[fileName]->editorRevision() == doc->editorRevision()) { + if (m_cppDocMap[fileName].revision() == doc->revision() + && m_cppDocMap[fileName].editorRevision() == doc->editorRevision()) { qDebug("Skipped due revision equality"); // added to verify if this ever happens.. return; } @@ -272,10 +269,8 @@ void TestCodeParser::removeFiles(const QStringList &files) { foreach (const QString file, files) { if (m_cppDocMap.contains(file)) { - TestInfo *info = m_cppDocMap.value(file); m_cppDocMap.remove(file); m_model->removeAutoTestSubtreeByFilePath(file); - delete info; } } } @@ -296,11 +291,6 @@ void TestCodeParser::scanForTests() void TestCodeParser::clearMaps() { - QMap::iterator it = m_cppDocMap.begin(); - while (it != m_cppDocMap.end()) { - delete it.value(); - ++it; - } m_cppDocMap.clear(); } diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index aeeb2d69724..192a9ca2208 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -55,7 +55,7 @@ private: void clearMaps(); TestTreeModel *m_model; - QMap m_cppDocMap; + QMap m_cppDocMap; ProjectExplorer::Project *m_currentProject; }; diff --git a/plugins/autotest/testinfo.h b/plugins/autotest/testinfo.h index 91b6be99960..c03236416da 100644 --- a/plugins/autotest/testinfo.h +++ b/plugins/autotest/testinfo.h @@ -27,7 +27,8 @@ namespace Internal { class TestInfo { public: - explicit TestInfo(const QString &className, const QStringList &functions = QStringList(), + explicit TestInfo(const QString &className = QString(), + const QStringList &functions = QStringList(), unsigned revision = 0, unsigned editorRevision = 0); ~TestInfo(); From 9394a43128fa21089bcc5ece18e84bb5a23530ca Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 5 Nov 2014 15:27:49 +0100 Subject: [PATCH 011/200] Add summary to results pane --- plugins/autotest/testresultmodel.cpp | 8 +++ plugins/autotest/testresultmodel.h | 2 + plugins/autotest/testresultspane.cpp | 76 +++++++++++++++++++++++----- plugins/autotest/testresultspane.h | 6 +++ 4 files changed, 79 insertions(+), 13 deletions(-) diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index ed03bae173f..24a37c4886f 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -108,6 +108,8 @@ void TestResultModel::addTestResult(const TestResult &testResult) { beginInsertRows(QModelIndex(), m_testResults.size(), m_testResults.size()); m_testResults.append(testResult); + int count = m_testResultCount.value(testResult.result(), 0); + m_testResultCount.insert(testResult.result(), ++count); endInsertRows(); m_availableResultTypes.insert(testResult.result()); } @@ -118,6 +120,7 @@ void TestResultModel::clearTestResults() return; beginRemoveRows(QModelIndex(), 0, m_testResults.size() - 1); m_testResults.clear(); + m_testResultCount.clear(); m_lastMaxWidthIndex = 0; m_maxWidthOfFileName = 0; m_widthOfLineNumber = 0; @@ -165,6 +168,11 @@ int TestResultModel::maxWidthOfLineNumber(const QFont &font) return m_widthOfLineNumber; } +int TestResultModel::resultTypeCount(ResultType type) +{ + return m_testResultCount.value(type, 0); +} + /********************************** Filter Model **********************************/ TestResultFilterModel::TestResultFilterModel(TestResultModel *sourceModel, QObject *parent) diff --git a/plugins/autotest/testresultmodel.h b/plugins/autotest/testresultmodel.h index c803d113b6f..95925bf4d0a 100644 --- a/plugins/autotest/testresultmodel.h +++ b/plugins/autotest/testresultmodel.h @@ -53,6 +53,7 @@ public: void enableAllResultTypes(); void toggleTestResultType(ResultType type); bool hasResultType(ResultType type) { return m_availableResultTypes.contains(type); } + int resultTypeCount(ResultType type); signals: @@ -60,6 +61,7 @@ public slots: private: QList m_testResults; + QMap m_testResultCount; int m_widthOfLineNumber; int m_maxWidthOfFileName; int m_lastMaxWidthIndex; diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index eee9fc93408..c7e28bf8c79 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -28,9 +28,12 @@ #include #include +#include #include +#include #include +#include namespace Autotest { namespace Internal { @@ -39,7 +42,31 @@ TestResultsPane::TestResultsPane(QObject *parent) : Core::IOutputPane(parent), m_context(new Core::IContext(this)) { - m_listView = new Utils::ListView; + m_outputWidget = new QWidget; + QVBoxLayout *outputLayout = new QVBoxLayout; + outputLayout->setMargin(0); + outputLayout->setSpacing(0); + m_outputWidget->setLayout(outputLayout); + + QPalette pal; + pal.setColor(QPalette::Window, + Utils::creatorTheme()->color(Utils::Theme::SearchResultWidgetBackgroundColor)); + pal.setColor(QPalette::WindowText, + Utils::creatorTheme()->color(Utils::Theme::SearchResultWidgetTextColor)); + m_summaryWidget = new QFrame; + m_summaryWidget->setPalette(pal); + m_summaryWidget->setAutoFillBackground(true); + QHBoxLayout *layout = new QHBoxLayout; + layout->setMargin(6); + m_summaryWidget->setLayout(layout); + m_summaryLabel = new QLabel; + m_summaryLabel->setPalette(pal); + layout->addWidget(m_summaryLabel); + m_summaryWidget->setVisible(false); + + outputLayout->addWidget(m_summaryWidget); + + m_listView = new Utils::ListView(m_outputWidget); m_model = new TestResultModel(this); m_filterModel = new TestResultFilterModel(m_model, this); m_filterModel->setDynamicSortFilter(true); @@ -47,6 +74,8 @@ TestResultsPane::TestResultsPane(QObject *parent) : TestResultDelegate *trd = new TestResultDelegate(this); m_listView->setItemDelegate(trd); + outputLayout->addWidget(m_listView); + createToolButtons(); connect(m_listView, &Utils::ListView::activated, this, &TestResultsPane::onItemActivated); @@ -117,12 +146,12 @@ void TestResultsPane::addTestResult(const TestResult &result) QWidget *TestResultsPane::outputWidget(QWidget *parent) { - if (m_listView) { - m_listView->setParent(parent); + if (m_outputWidget) { + m_outputWidget->setParent(parent); } else { - m_listView = new Utils::ListView(parent); + qDebug() << "This should not happen..."; } - return m_listView; + return m_outputWidget; } QList TestResultsPane::toolBarWidgets() const @@ -144,6 +173,7 @@ void TestResultsPane::clearContents() { m_filterModel->clearTestResults(); navigateStateChanged(); + m_summaryWidget->setVisible(false); } void TestResultsPane::visibilityChanged(bool) @@ -242,14 +272,14 @@ void TestResultsPane::onRunSelectedTriggered() void TestResultsPane::initializeFilterMenu() { QMap textAndType; - textAndType.insert(ResultType::PASS, QLatin1String("Pass")); - textAndType.insert(ResultType::FAIL, QLatin1String("Fail")); - textAndType.insert(ResultType::EXPECTED_FAIL, QLatin1String("Expected Fail")); - textAndType.insert(ResultType::UNEXPECTED_PASS, QLatin1String("Unexpected Pass")); - textAndType.insert(ResultType::SKIP, QLatin1String("Skip")); - textAndType.insert(ResultType::MESSAGE_DEBUG, QLatin1String("Debug Messages")); - textAndType.insert(ResultType::MESSAGE_WARN, QLatin1String("Warning Messages")); - textAndType.insert(ResultType::MESSAGE_INTERNAL, QLatin1String("Internal Messages")); + textAndType.insert(ResultType::PASS, tr("Pass")); + textAndType.insert(ResultType::FAIL, tr("Fail")); + textAndType.insert(ResultType::EXPECTED_FAIL, tr("Expected Fail")); + textAndType.insert(ResultType::UNEXPECTED_PASS, tr("Unexpected Pass")); + textAndType.insert(ResultType::SKIP, tr("Skip")); + textAndType.insert(ResultType::MESSAGE_DEBUG, tr("Debug Messages")); + textAndType.insert(ResultType::MESSAGE_WARN, tr("Warning Messages")); + textAndType.insert(ResultType::MESSAGE_INTERNAL, tr("Internal Messages")); foreach (ResultType result, textAndType.keys()) { QAction *action = new QAction(m_filterMenu); action->setText(textAndType.value(result)); @@ -260,6 +290,23 @@ void TestResultsPane::initializeFilterMenu() } } +void TestResultsPane::updateSummaryLabel() +{ + QString labelText = QString::fromLatin1("

Test Summary:   %1 %2, %3 %4") + .arg(QString::number(m_model->resultTypeCount(ResultType::PASS)), tr("passes"), + QString::number(m_model->resultTypeCount(ResultType::FAIL)), tr("fails")); + int count = m_model->resultTypeCount(ResultType::UNEXPECTED_PASS); + if (count) + labelText.append(QString::fromLatin1(", %1 %2") + .arg(QString::number(count), tr("unexpected passes"))); + count = m_model->resultTypeCount(ResultType::EXPECTED_FAIL); + if (count) + labelText.append(QString::fromLatin1(", %1 %2") + .arg(QString::number(count), tr("expected fails"))); + labelText.append(QLatin1String(".

")); + m_summaryLabel->setText(labelText); +} + void TestResultsPane::updateFilterMenu() { foreach (QAction *action, m_filterMenu->actions()) { @@ -279,6 +326,7 @@ void TestResultsPane::onTestRunStarted() m_stopTestRun->setEnabled(true); m_runAll->setEnabled(false); m_runSelected->setEnabled(false); + m_summaryWidget->setVisible(false); } void TestResultsPane::onTestRunFinished() @@ -286,6 +334,8 @@ void TestResultsPane::onTestRunFinished() m_stopTestRun->setEnabled(false); m_runAll->setEnabled(true); m_runSelected->setEnabled(true); + updateSummaryLabel(); + m_summaryWidget->setVisible(true); } void TestResultsPane::onTestTreeModelChanged() diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h index 58363cbb044..ea33c5f0e99 100644 --- a/plugins/autotest/testresultspane.h +++ b/plugins/autotest/testresultspane.h @@ -23,6 +23,8 @@ QT_BEGIN_NAMESPACE class QAction; +class QFrame; +class QLabel; class QModelIndex; class QMenu; class QToolButton; @@ -82,11 +84,15 @@ private slots: private: explicit TestResultsPane(QObject *parent = 0); void initializeFilterMenu(); + void updateSummaryLabel(); void createToolButtons(); void onTestRunStarted(); void onTestRunFinished(); void onTestTreeModelChanged(); + QWidget *m_outputWidget; + QFrame *m_summaryWidget; + QLabel *m_summaryLabel; Utils::ListView *m_listView; TestResultModel *m_model; TestResultFilterModel *m_filterModel; From 1145febc05559b47a54717264564e64ba5f8d41c Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 5 Nov 2014 15:40:37 +0100 Subject: [PATCH 012/200] Add 'Check All Filter' action to filter menu --- plugins/autotest/testresultmodel.h | 2 -- plugins/autotest/testresultspane.cpp | 20 ++++++++++++++++++-- plugins/autotest/testresultspane.h | 1 + 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/plugins/autotest/testresultmodel.h b/plugins/autotest/testresultmodel.h index 95925bf4d0a..7618512fa26 100644 --- a/plugins/autotest/testresultmodel.h +++ b/plugins/autotest/testresultmodel.h @@ -50,8 +50,6 @@ public: int maxWidthOfFileName(const QFont &font); int maxWidthOfLineNumber(const QFont &font); - void enableAllResultTypes(); - void toggleTestResultType(ResultType type); bool hasResultType(ResultType type) { return m_availableResultTypes.contains(type); } int resultTypeCount(ResultType type); diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index c7e28bf8c79..e903aecffd8 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -288,6 +288,12 @@ void TestResultsPane::initializeFilterMenu() action->setData(result); m_filterMenu->addAction(action); } + m_filterMenu->addSeparator(); + QAction *action = new QAction(m_filterMenu); + action->setText(tr("Check All Filters")); + action->setCheckable(false); + m_filterMenu->addAction(action); + connect(action, &QAction::triggered, this, &TestResultsPane::enableAllFilter); } void TestResultsPane::updateSummaryLabel() @@ -310,11 +316,21 @@ void TestResultsPane::updateSummaryLabel() void TestResultsPane::updateFilterMenu() { foreach (QAction *action, m_filterMenu->actions()) { - action->setEnabled(m_model->hasResultType( - static_cast(action->data().value()))); + if (action->isCheckable()) + action->setEnabled(m_model->hasResultType( + static_cast(action->data().value()))); } } +void TestResultsPane::enableAllFilter() +{ + foreach (QAction *action, m_filterMenu->actions()) { + if (action->isCheckable()) + action->setChecked(true); + } + m_filterModel->enableAllResultTypes(); +} + void TestResultsPane::filterMenuTriggered(QAction *action) { m_filterModel->toggleTestResultType(static_cast(action->data().value())); diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h index ea33c5f0e99..338eca79014 100644 --- a/plugins/autotest/testresultspane.h +++ b/plugins/autotest/testresultspane.h @@ -79,6 +79,7 @@ private slots: void onRunAllTriggered(); void onRunSelectedTriggered(); void updateFilterMenu(); + void enableAllFilter(); void filterMenuTriggered(QAction *action); private: From a2a4fe564a170dd65f509e63e77fdf65a78a5c6b Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 5 Nov 2014 15:52:34 +0100 Subject: [PATCH 013/200] Cancel process when timeout is reached... ...and display fatal messages on the summary as well. --- plugins/autotest/testresultspane.cpp | 4 ++++ plugins/autotest/testrunner.cpp | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index e903aecffd8..d14b7567cae 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -309,6 +309,10 @@ void TestResultsPane::updateSummaryLabel() if (count) labelText.append(QString::fromLatin1(", %1 %2") .arg(QString::number(count), tr("expected fails"))); + count = m_model->resultTypeCount(ResultType::MESSAGE_FATAL); + if (count) + labelText.append(QString::fromLatin1(", %1 %2") + .arg(QString::number(count), tr("fatals"))); labelText.append(QLatin1String(".

")); m_summaryLabel->setText(labelText); } diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 4591f94081f..fb4028edf09 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -288,6 +288,14 @@ bool performExec(const QString &cmd, const QStringList &args, const QString &wor if (ok && executionTimer.elapsed() < timeout) { return m_runner->exitCode() == 0; } else { + if (m_runner->state() != QProcess::NotRunning) { + m_runner->kill(); + m_runner->waitForFinished(); + TestResultsPane::instance()->addTestResult( + TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, + QObject::tr("*** Test Case canceled due to timeout ***\n" + "Maybe raise the timeout?"))); + } return false; } } From 1258c58a7f74f8113edc4781baacaa68f7fe9d44 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 6 Nov 2014 10:48:17 +0100 Subject: [PATCH 014/200] Disable context menu on test tree when executing test --- plugins/autotest/testrunner.cpp | 12 ++++++++++-- plugins/autotest/testrunner.h | 3 +++ plugins/autotest/testtreeview.cpp | 10 ++++++---- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index fb4028edf09..e4b16ccbc4c 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -52,7 +52,8 @@ TestRunner *TestRunner::instance() TestRunner::TestRunner(QObject *parent) : QObject(parent), - m_building(false) + m_building(false), + m_executingTests(false) { } @@ -375,12 +376,13 @@ void TestRunner::runTests() } } + m_executingTests = true; emit testRunStarted(); QFuture future = QtConcurrent::run(&performTestRun , m_selectedTests); Core::FutureProgress *progress = Core::ProgressManager::addTask(future, tr("Running Tests"), Autotest::Constants::TASK_INDEX); connect(progress, &Core::FutureProgress::finished, - TestRunner::instance(), &TestRunner::testRunFinished); + TestRunner::instance(), &TestRunner::onFinished); } void TestRunner::buildProject(ProjectExplorer::Project *project) @@ -405,6 +407,12 @@ void TestRunner::buildFinished(bool success) m_buildSucceeded = success; } +void TestRunner::onFinished() +{ + m_executingTests = false; + emit testRunFinished(); +} + void TestRunner::stopTestRun() { if (m_runner && m_runner->state() != QProcess::NotRunning && m_currentFuture) diff --git a/plugins/autotest/testrunner.h b/plugins/autotest/testrunner.h index 1a725eada77..6b739b15941 100644 --- a/plugins/autotest/testrunner.h +++ b/plugins/autotest/testrunner.h @@ -41,6 +41,7 @@ public: ~TestRunner(); void setSelectedTests(const QList &selected); + bool isTestRunning() const { return m_executingTests; } signals: void testRunStarted(); @@ -53,6 +54,7 @@ public slots: private slots: void buildProject(ProjectExplorer::Project *project); void buildFinished(bool success); + void onFinished(); private: explicit TestRunner(QObject *parent = 0); @@ -60,6 +62,7 @@ private: QList m_selectedTests; bool m_building; bool m_buildSucceeded; + bool m_executingTests; }; diff --git a/plugins/autotest/testtreeview.cpp b/plugins/autotest/testtreeview.cpp index fc2fffe1c1d..d16e43c6039 100644 --- a/plugins/autotest/testtreeview.cpp +++ b/plugins/autotest/testtreeview.cpp @@ -71,6 +71,7 @@ TestTreeViewWidget::TestTreeViewWidget(QWidget *parent) : void TestTreeViewWidget::contextMenuEvent(QContextMenuEvent *event) { + bool enabled = !TestRunner::instance()->isTestRunning(); bool hasTests = m_model->hasTests(); QMenu menu; QAction *runAll = new QAction(tr("Run All Tests"), &menu); @@ -87,10 +88,11 @@ void TestTreeViewWidget::contextMenuEvent(QContextMenuEvent *event) connect(rescan, &QAction::triggered, TestTreeModel::instance()->parser(), &TestCodeParser::updateTestTree); - runAll->setEnabled(hasTests); - runSelected->setEnabled(hasTests); - selectAll->setEnabled(hasTests); - deselectAll->setEnabled(hasTests); + runAll->setEnabled(enabled && hasTests); + runSelected->setEnabled(enabled && hasTests); + selectAll->setEnabled(enabled && hasTests); + deselectAll->setEnabled(enabled && hasTests); + rescan->setEnabled(enabled); menu.addAction(runAll); menu.addAction(runSelected); From 85efa2c3c969392afbe869ed0fc4a4af91c739f4 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 6 Nov 2014 12:12:39 +0100 Subject: [PATCH 015/200] Update internal cache / test tree only if necessary --- plugins/autotest/testcodeparser.cpp | 31 ++++++++++++++++------------ plugins/autotest/testresultspane.cpp | 4 ++-- plugins/autotest/testtreeview.cpp | 8 +++---- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 61c0e03933e..23006677feb 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -213,16 +213,19 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) break; } } - info = m_cppDocMap.value(declFileName); - count = autoTestRootItem->childCount(); - for (int i = 0; i < count; ++i) { - TestTreeItem *currentItem = autoTestRootItem->child(i); - if (currentItem->filePath() == declFileName) { - m_model->modifyAutoTestSubtree(i, ttItem); - TestInfo ti(tc, privSlots.keys(), doc->revision(), doc->editorRevision()); - ti.setReferencingFile(file); - m_cppDocMap.insert(declFileName, ti); - break; + if (declFileName != file) { + info = m_cppDocMap.value(declFileName); + count = autoTestRootItem->childCount(); + for (int i = 0; i < count; ++i) { + TestTreeItem *currentItem = autoTestRootItem->child(i); + if (currentItem->filePath() == declFileName) { + m_model->modifyAutoTestSubtree(i, ttItem); + TestInfo ti(tc, privSlots.keys(), doc->revision(), + doc->editorRevision()); + ti.setReferencingFile(file); + m_cppDocMap.insert(declFileName, ti); + break; + } } } delete ttItem; @@ -230,9 +233,11 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) m_model->addAutoTest(ttItem); m_cppDocMap.insert(file, TestInfo(tc, privSlots.keys(), doc->revision(), doc->editorRevision())); - TestInfo ti(tc, privSlots.keys(), doc->revision(), doc->editorRevision()); - ti.setReferencingFile(file); - m_cppDocMap.insert(declFileName, ti); + if (declFileName != file) { + TestInfo ti(tc, privSlots.keys(), doc->revision(), doc->editorRevision()); + ti.setReferencingFile(file); + m_cppDocMap.insert(declFileName, ti); + } } } } else { diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index d14b7567cae..06a3257b0a1 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -250,7 +250,7 @@ void TestResultsPane::onItemActivated(const QModelIndex &index) if (!index.isValid()) return; - TestResult tr = m_filterModel->testResult(index); + const TestResult tr = m_filterModel->testResult(index); if (!tr.fileName().isEmpty()) Core::EditorManager::openEditorAt(tr.fileName(), tr.line(), 0); } @@ -360,7 +360,7 @@ void TestResultsPane::onTestRunFinished() void TestResultsPane::onTestTreeModelChanged() { - bool enable = TestTreeModel::instance()->hasTests(); + const bool enable = TestTreeModel::instance()->hasTests(); m_runAll->setEnabled(enable); m_runSelected->setEnabled(enable); } diff --git a/plugins/autotest/testtreeview.cpp b/plugins/autotest/testtreeview.cpp index d16e43c6039..73d0fbbbd9e 100644 --- a/plugins/autotest/testtreeview.cpp +++ b/plugins/autotest/testtreeview.cpp @@ -71,8 +71,8 @@ TestTreeViewWidget::TestTreeViewWidget(QWidget *parent) : void TestTreeViewWidget::contextMenuEvent(QContextMenuEvent *event) { - bool enabled = !TestRunner::instance()->isTestRunning(); - bool hasTests = m_model->hasTests(); + const bool enabled = !TestRunner::instance()->isTestRunning(); + const bool hasTests = m_model->hasTests(); QMenu menu; QAction *runAll = new QAction(tr("Run All Tests"), &menu); QAction *runSelected = new QAction(tr("Run Selected Tests"), &menu); @@ -207,14 +207,14 @@ void TestTreeView::deselectAll() // this avoids the re-evaluation of parent nodes when modifying the child nodes (setData()) void TestTreeView::selectOrDeselectAll(const Qt::CheckState checkState) { - TestTreeModel *model = TestTreeModel::instance(); + const TestTreeModel *model = TestTreeModel::instance(); QModelIndex autoTestsIndex = model->index(0, 0, rootIndex()); if (!autoTestsIndex.isValid()) return; int count = model->rowCount(autoTestsIndex); QModelIndex last; for (int i = 0; i < count; ++i) { - QModelIndex classesIndex = model->index(i, 0, autoTestsIndex); + const QModelIndex classesIndex = model->index(i, 0, autoTestsIndex); int funcCount = model->rowCount(classesIndex); TestTreeItem *item = static_cast(classesIndex.internalPointer()); if (item) { From 0357b0e98bf049ddb2e365a6ddcace67c2f0e836 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 6 Nov 2014 16:01:06 +0100 Subject: [PATCH 016/200] Add basic support for Qt Quick Test --- plugins/autotest/autotest_dependencies.pri | 2 + plugins/autotest/testcodeparser.cpp | 299 ++++++++++++++++++++- plugins/autotest/testcodeparser.h | 7 +- plugins/autotest/testconfiguration.cpp | 20 ++ plugins/autotest/testconfiguration.h | 2 + plugins/autotest/testrunner.cpp | 2 +- plugins/autotest/testtreeitem.cpp | 4 + plugins/autotest/testtreeitem.h | 3 + plugins/autotest/testtreemodel.cpp | 262 ++++++++++++++---- plugins/autotest/testtreemodel.h | 11 +- plugins/autotest/testtreeview.cpp | 53 ++-- plugins/autotest/testvisitor.cpp | 79 +++++- plugins/autotest/testvisitor.h | 27 ++ 13 files changed, 681 insertions(+), 90 deletions(-) diff --git a/plugins/autotest/autotest_dependencies.pri b/plugins/autotest/autotest_dependencies.pri index c5d76107a00..6546683f456 100644 --- a/plugins/autotest/autotest_dependencies.pri +++ b/plugins/autotest/autotest_dependencies.pri @@ -4,10 +4,12 @@ QTC_PLUGIN_DEPENDS += \ coreplugin \ projectexplorer \ cpptools \ + qmljstools \ licensechecker QTC_LIB_DEPENDS += \ cplusplus \ + qmljs \ utils #QTC_PLUGIN_RECOMMENDS += \ diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 23006677feb..f58b2a44891 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -30,6 +30,10 @@ #include +#include +#include +#include + #include namespace Autotest { @@ -53,6 +57,7 @@ void TestCodeParser::updateTestTree() clearMaps(); m_model->removeAllAutoTests(); + m_model->removeAllQuickTests(); const ProjectExplorer::SessionManager *session = ProjectExplorer::SessionManager::instance(); if (!session || !session->hasProjects()) return; @@ -88,7 +93,7 @@ static bool includesQtTest(const CPlusPlus::Document::Ptr &doc, { const QList includes = doc->resolvedIncludes(); - foreach (const CPlusPlus::Document::Include inc, includes) { + foreach (const CPlusPlus::Document::Include &inc, includes) { // TODO this short cut works only for #include // bad, as there could be much more different approaches if (inc.unresolvedFileName() == QLatin1String("QtTest") @@ -100,7 +105,7 @@ static bool includesQtTest(const CPlusPlus::Document::Ptr &doc, if (cppMM) { CPlusPlus::Snapshot snapshot = cppMM->snapshot(); const QSet allIncludes = snapshot.allIncludesForDocument(doc->fileName()); - foreach (const QString include, allIncludes) { + foreach (const QString &include, allIncludes) { if (include.endsWith(QLatin1String("QtTest/qtest.h"))) { return true; } @@ -109,6 +114,27 @@ static bool includesQtTest(const CPlusPlus::Document::Ptr &doc, return false; } +static bool includesQtQuickTest(const CPlusPlus::Document::Ptr &doc, + const CppTools::CppModelManager *cppMM) +{ + const QList includes = doc->resolvedIncludes(); + + foreach (const CPlusPlus::Document::Include &inc, includes) { + if (inc.unresolvedFileName() == QLatin1String("QtQuickTest/quicktest.h") + && inc.resolvedFileName().endsWith(QLatin1String("QtQuickTest/quicktest.h"))) { + return true; + } + } + + if (cppMM) { + foreach (const QString &include, cppMM->snapshot().allIncludesForDocument(doc->fileName())) { + if (include.endsWith(QLatin1String("QtQuickTest/quicktest.h"))) + return true; + } + } + return false; +} + static bool qtTestLibDefined(const CppTools::CppModelManager *cppMM, const QString &fileName) { @@ -118,24 +144,91 @@ static bool qtTestLibDefined(const CppTools::CppModelManager *cppMM, return false; } +static QString quickTestSrcDir(const CppTools::CppModelManager *cppMM, + const QString &fileName) +{ + static const QByteArray qtsd(" QUICK_TEST_SOURCE_DIR "); + const QList parts = cppMM->projectPart(fileName); + if (parts.size() > 0) { + QByteArray projDefines(parts.at(0)->projectDefines); + foreach (const QByteArray &line, projDefines.split('\n')) { + if (line.contains(qtsd)) { + QByteArray result = line.mid(line.indexOf(qtsd) + qtsd.length()); + if (result.startsWith('"')) + result.remove(result.length() - 1, 1).remove(0, 1); + if (result.startsWith("\\\"")) + result.remove(result.length() - 2, 2).remove(0, 2); + return QLatin1String(result); + } + } + } + return QString(); +} + static QString testClass(const CPlusPlus::Document::Ptr &doc) { - static QByteArray qtTestMacros[] = {"QTEST_MAIN", "QTEST_APPLESS_MAIN", "QTEST_GUILESS_MAIN"}; - QString tC; + static const QByteArray qtTestMacros[] = {"QTEST_MAIN", "QTEST_APPLESS_MAIN", "QTEST_GUILESS_MAIN"}; const QList macros = doc->macroUses(); - foreach (const CPlusPlus::Document::MacroUse macro, macros) { + foreach (const CPlusPlus::Document::MacroUse ¯o, macros) { + if (!macro.isFunctionLike()) + continue; + const QByteArray name = macro.macro().name(); + if (name == qtTestMacros[0] || name == qtTestMacros[1] || name == qtTestMacros[2]) { + const CPlusPlus::Document::Block arg = macro.arguments().at(0); + return QLatin1String(getFileContent(doc->fileName()).mid(arg.bytesBegin(), arg.bytesEnd() - arg.bytesBegin())); + } + } + return QString(); +} + +static QString quickTestName(const CPlusPlus::Document::Ptr &doc) +{ + static const QByteArray qtTestMacros[] = {"QUICK_TEST_MAIN", "QUICK_TEST_OPENGL_MAIN"}; + const QList macros = doc->macroUses(); + + foreach (const CPlusPlus::Document::MacroUse ¯o, macros) { if (!macro.isFunctionLike()) continue; const QByteArray name = macro.macro().name(); if (name == qtTestMacros[0] || name == qtTestMacros[1] || name == qtTestMacros[2]) { CPlusPlus::Document::Block arg = macro.arguments().at(0); - tC = QLatin1String(getFileContent(doc->fileName()).mid(arg.bytesBegin(), - arg.bytesEnd() - arg.bytesBegin())); - break; + return QLatin1String(getFileContent(doc->fileName()).mid(arg.bytesBegin(), arg.bytesEnd() - arg.bytesBegin())); } } - return tC; + return QString(); +} + +static QList scanDirectoryForQuickTestQmlFiles(const QString &srcDir) +{ + QStringList dirs(srcDir); + QmlJS::ModelManagerInterface *qmlJsMM = QmlJSTools::Internal::ModelManager::instance(); + // make sure even files not listed in pro file are available inside the snapshot + QFutureInterface future; + QmlJS::PathsAndLanguages paths; + paths.maybeInsert(Utils::FileName::fromString(srcDir), QmlJS::Dialect::Qml); + QmlJS::ModelManagerInterface::importScan(future, qmlJsMM->workingCopy(), + paths, qmlJsMM, false, false); + + const QmlJS::Snapshot snapshot = QmlJSTools::Internal::ModelManager::instance()->snapshot(); + QDirIterator it(srcDir, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + while (it.hasNext()) { + it.next(); + QFileInfo fi(it.fileInfo().canonicalFilePath()); + dirs << fi.filePath(); + } + QList foundDocs; + + foreach (const QString &path, dirs) { + const QList docs = snapshot.documentsInDirectory(path); + foreach (const QmlJS::Document::Ptr &doc, docs) { + const QString fileName(QFileInfo(doc->fileName()).fileName()); + if (fileName.startsWith(QLatin1String("tst_")) && fileName.endsWith(QLatin1String(".qml"))) + foundDocs << doc; + } + } + + return foundDocs; } /****** end of helpers ******/ @@ -145,6 +238,11 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) const QString file = doc->fileName(); const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + if (includesQtQuickTest(doc, cppMM)) { + handleQtQuickTest(doc); + return; + } + if (includesQtTest(doc, cppMM) && qtTestLibDefined(cppMM, file)) { QString tc(testClass(doc)); if (tc.isEmpty()) { @@ -187,7 +285,7 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) TestVisitor myVisitor(tc); myVisitor.accept(declaringDoc->globalNamespace()); const QMap privSlots = myVisitor.privateSlots(); - foreach (const QString privS, privSlots.keys()) { + foreach (const QString &privS, privSlots.keys()) { const TestCodeLocation location = privSlots.value(privS); TestTreeItem *ttSub = new TestTreeItem(privS, location.m_fileName, TestTreeItem::TEST_FUNCTION, ttItem); @@ -253,7 +351,143 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) } } -void TestCodeParser::onDocumentUpdated(CPlusPlus::Document::Ptr doc) +void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr doc) +{ + const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + + if (quickTestName(doc).isEmpty()) + return; + + const QString srcDir = quickTestSrcDir(cppMM, doc->fileName()); + if (srcDir.isEmpty()) + return; + + const QList qmlDocs = scanDirectoryForQuickTestQmlFiles(srcDir); + foreach (const QmlJS::Document::Ptr &d, qmlDocs) { + QmlJS::AST::Node *ast = d->ast(); + if (!ast) { + qDebug() << "ast is zero pointer" << d->fileName(); // should not happen + continue; + } + TestQmlVisitor qmlVisitor(d); + QmlJS::AST::Node::accept(ast, &qmlVisitor); + + const QString tcName = qmlVisitor.testCaseName(); + const TestCodeLocation tcLocation = qmlVisitor.testCaseLocation(); + const QMap testFunctions = qmlVisitor.testFunctions(); + + const QModelIndex quickTestRootIndex = m_model->index(1, 0); + TestTreeItem *quickTestRootItem = static_cast(quickTestRootIndex.internalPointer()); + + if (tcName.isEmpty()) { + // if this test case was named before remove it + if (m_quickDocMap.contains(d->fileName())) { + m_model->removeQuickTestSubtreeByFilePath(d->fileName()); + m_quickDocMap.remove(d->fileName()); + } + bool hadUnnamedTestsBefore; + TestTreeItem *ttItem = m_model->unnamedQuickTests(); + if (!ttItem) { + hadUnnamedTestsBefore = false; + ttItem = new TestTreeItem(QString(), QString(), TestTreeItem::TEST_CLASS, + quickTestRootItem); + foreach (const QString &func, testFunctions.keys()) { + const TestCodeLocation location = testFunctions.value(func); + TestTreeItem *ttSub = new TestTreeItem(func, location.m_fileName, + TestTreeItem::TEST_FUNCTION, ttItem); + ttSub->setLine(location.m_line); + ttSub->setColumn(location.m_column); + ttSub->setMainFile(doc->fileName()); + ttItem->appendChild(ttSub); + } + } else { + hadUnnamedTestsBefore = true; + // remove unnamed quick tests that are already found for this qml file + m_model->removeUnnamedQuickTest(d->fileName()); + + foreach (const QString &func, testFunctions.keys()) { + const TestCodeLocation location = testFunctions.value(func); + TestTreeItem *ttSub = new TestTreeItem(func, location.m_fileName, + TestTreeItem::TEST_FUNCTION, ttItem); + ttSub->setLine(location.m_line); + ttSub->setColumn(location.m_column); + ttSub->setMainFile(doc->fileName()); + ttItem->appendChild(ttSub); + } + } + TestInfo info = m_quickDocMap.contains(QLatin1String("")) + ? m_quickDocMap[QLatin1String("")] + : TestInfo(QString(), QStringList(), 666); + QStringList originalFunctions(info.testFunctions()); + foreach (const QString &func, testFunctions.keys()) { + if (!originalFunctions.contains(func)) + originalFunctions.append(func); + } + info.setTestFunctions(originalFunctions); + + if (hadUnnamedTestsBefore) + m_model->modifyQuickTestSubtree(ttItem->row(), ttItem); + else + m_model->addQuickTest(ttItem); + m_quickDocMap.insert(QLatin1String(""), info); + + continue; + } // end of handling test cases without name property + + // construct new/modified TestTreeItem + TestTreeItem *ttItem = new TestTreeItem(tcName, tcLocation.m_fileName, + TestTreeItem::TEST_CLASS, quickTestRootItem); + ttItem->setLine(tcLocation.m_line); + ttItem->setColumn(tcLocation.m_column); + ttItem->setMainFile(doc->fileName()); + + foreach (const QString &func, testFunctions.keys()) { + const TestCodeLocation location = testFunctions.value(func); + TestTreeItem *ttSub = new TestTreeItem(func, location.m_fileName, + TestTreeItem::TEST_FUNCTION, ttItem); + ttSub->setLine(location.m_line); + ttSub->setColumn(location.m_column); + ttItem->appendChild(ttSub); + } + + // update model and internal map + const QString fileName(tcLocation.m_fileName); + const QmlJS::Document::Ptr qmlDoc = + QmlJSTools::Internal::ModelManager::instance()->snapshot().document(fileName); + + if (m_quickDocMap.contains(fileName)) { + for (int i = 0; i < quickTestRootItem->childCount(); ++i) { + if (quickTestRootItem->child(i)->filePath() == fileName) { + m_model->modifyQuickTestSubtree(i, ttItem); + TestInfo ti(tcName, testFunctions.keys(), 0, qmlDoc->editorRevision()); + ti.setReferencingFile(doc->fileName()); + m_quickDocMap.insert(fileName, ti); + break; + } + } + delete ttItem; + } else { + // if it was formerly unnamed remove the respective items + if (m_quickDocMap.contains(QLatin1String(""))) { + m_model->removeUnnamedQuickTest(d->fileName()); + TestInfo unnamedInfo = m_quickDocMap[QLatin1String("")]; + QStringList functions = unnamedInfo.testFunctions(); + foreach (const QString &func, testFunctions.keys()) + if (functions.contains(func)) + functions.removeOne(func); + unnamedInfo.setTestFunctions(functions); + m_quickDocMap.insert(QLatin1String(""), unnamedInfo); + } + + m_model->addQuickTest(ttItem); + TestInfo ti(tcName, testFunctions.keys(), 0, qmlDoc->editorRevision()); + ti.setReferencingFile(doc->fileName()); + m_quickDocMap.insert(tcLocation.m_fileName, ti); + } + } +} + +void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &doc) { if (!m_currentProject) return; @@ -270,13 +504,51 @@ void TestCodeParser::onDocumentUpdated(CPlusPlus::Document::Ptr doc) checkDocumentForTestCode(doc); } +void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &doc) +{ + if (!m_currentProject) + return; + const QString fileName = doc->fileName(); + if (m_quickDocMap.contains(fileName)) { + if ((int)m_quickDocMap[fileName].editorRevision() == doc->editorRevision()) { + qDebug("Skipped due revision equality (QML)"); // added to verify this ever happens.... + return; + } + } else if (!m_currentProject->files(ProjectExplorer::Project::AllFiles).contains(fileName)) { + // what if the file is not listed inside the pro file, but will be used anyway? + return; + } + const CPlusPlus::Snapshot snapshot = CppTools::CppModelManager::instance()->snapshot(); + if (m_quickDocMap.contains(fileName) + && snapshot.contains(m_quickDocMap[fileName].referencingFile())) { + checkDocumentForTestCode(snapshot.document(m_quickDocMap[fileName].referencingFile())); + } + if (!m_quickDocMap.contains(QLatin1String(""))) + return; + + // special case of having unnamed TestCases + TestTreeItem *unnamed = m_model->unnamedQuickTests(); + for (int row = 0, count = unnamed->childCount(); row < count; ++row) { + const TestTreeItem *child = unnamed->child(row); + if (fileName == child->filePath()) { + if (snapshot.contains(child->mainFile())) + checkDocumentForTestCode(snapshot.document(child->mainFile())); + break; + } + } +} + void TestCodeParser::removeFiles(const QStringList &files) { - foreach (const QString file, files) { + foreach (const QString &file, files) { if (m_cppDocMap.contains(file)) { m_cppDocMap.remove(file); m_model->removeAutoTestSubtreeByFilePath(file); } + if (m_quickDocMap.contains(file)) { + m_quickDocMap.remove(file); + m_model->removeQuickTestSubtreeByFilePath(file); + } } } @@ -286,7 +558,7 @@ void TestCodeParser::scanForTests() CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); CPlusPlus::Snapshot snapshot = cppMM->snapshot(); - foreach (const QString file, list) { + foreach (const QString &file, list) { if (snapshot.contains(file)) { CPlusPlus::Document::Ptr doc = snapshot.find(file).value(); checkDocumentForTestCode(doc); @@ -297,6 +569,7 @@ void TestCodeParser::scanForTests() void TestCodeParser::clearMaps() { m_cppDocMap.clear(); + m_quickDocMap.clear(); } } // namespace Internal diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 192a9ca2208..5b422ba0e6e 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -21,6 +21,8 @@ #include +#include + #include #include @@ -46,8 +48,10 @@ signals: public slots: void updateTestTree(); void checkDocumentForTestCode(CPlusPlus::Document::Ptr doc); + void handleQtQuickTest(CPlusPlus::Document::Ptr doc); - void onDocumentUpdated(CPlusPlus::Document::Ptr doc); + void onCppDocumentUpdated(const CPlusPlus::Document::Ptr &doc); + void onQmlDocumentUpdated(const QmlJS::Document::Ptr &doc); void removeFiles(const QStringList &files); private: @@ -56,6 +60,7 @@ private: TestTreeModel *m_model; QMap m_cppDocMap; + QMap m_quickDocMap; ProjectExplorer::Project *m_currentProject; }; diff --git a/plugins/autotest/testconfiguration.cpp b/plugins/autotest/testconfiguration.cpp index 4841a86fbfe..bcb90d75b5e 100644 --- a/plugins/autotest/testconfiguration.cpp +++ b/plugins/autotest/testconfiguration.cpp @@ -41,6 +41,26 @@ TestConfiguration::~TestConfiguration() m_testCases.clear(); } +/** + * @brief sets the test cases for this test configuration. + * + * Watch out for special handling of test configurations, because this method also + * updates the test case count to the current size of \a testCases. + * + * @param testCases list of names of the test functions / test cases + */ +void TestConfiguration::setTestCases(const QStringList &testCases) +{ + m_testCases.clear(); + m_testCases << testCases; + m_testCaseCount = m_testCases.size(); +} + +void TestConfiguration::setTestCaseCount(int count) +{ + m_testCaseCount = count; +} + void TestConfiguration::setTargetFile(const QString &targetFile) { m_targetFile = targetFile; diff --git a/plugins/autotest/testconfiguration.h b/plugins/autotest/testconfiguration.h index aab9d31db67..aa82b8e2b53 100644 --- a/plugins/autotest/testconfiguration.h +++ b/plugins/autotest/testconfiguration.h @@ -40,6 +40,8 @@ public: int testCaseCount = 0, QObject *parent = 0); ~TestConfiguration(); + void setTestCases(const QStringList &testCases); + void setTestCaseCount(int count); void setTargetFile(const QString &targetFile); void setTargetName(const QString &targetName); void setProFile(const QString &proFile); diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index e4b16ccbc4c..ed2383bb3f0 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -224,7 +224,7 @@ static QString which(const QString &path, const QString &cmd) paths = path.split(QLatin1Char(':')); #endif - foreach (const QString p, paths) { + foreach (const QString &p, paths) { const QString fName = p + QDir::separator() + cmd; QFileInfo fi(fName); if (fi.exists() && fi.isExecutable()) diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index 7fb8b85e198..3b7c27fcde4 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -94,6 +94,10 @@ bool TestTreeItem::modifyContent(const TestTreeItem *modified) m_line = modified->m_line; hasBeenModified = true; } + if (m_mainFile != modified->m_mainFile) { + m_mainFile = modified->m_mainFile; + hasBeenModified = true; + } return hasBeenModified; } diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index edda539fd36..eaa1d68656c 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -53,6 +53,8 @@ public: unsigned line() const { return m_line; } void setColumn(unsigned column) { m_column = column; } unsigned column() const { return m_column; } + QString mainFile() const { return m_mainFile; } + void setMainFile(const QString &mainFile) { m_mainFile = mainFile; } void setChecked(const Qt::CheckState checked); Qt::CheckState checked() const { return m_checked; } Type type() const { return m_type; } @@ -66,6 +68,7 @@ private: Type m_type; unsigned m_line; unsigned m_column; + QString m_mainFile; TestTreeItem *m_parent; QList m_children; }; diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 214afb110a4..38a38c51f93 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -43,11 +43,11 @@ TestTreeModel::TestTreeModel(QObject *parent) : QAbstractItemModel(parent), m_rootItem(new TestTreeItem(QString(), QString(), TestTreeItem::ROOT)), m_autoTestRootItem(new TestTreeItem(tr("Auto Tests"), QString(), TestTreeItem::ROOT, m_rootItem)), -// m_quickTestRootItem(new TestTreeItem(tr("Qt Quick Tests"), QString(), TestTreeItem::ROOT, m_rootItem)), + m_quickTestRootItem(new TestTreeItem(tr("Qt Quick Tests"), QString(), TestTreeItem::ROOT, m_rootItem)), m_parser(new TestCodeParser(this)) { m_rootItem->appendChild(m_autoTestRootItem); -// m_rootItem->appendChild(m_quickTestRootItem); + m_rootItem->appendChild(m_quickTestRootItem); m_parser->updateTestTree(); // CppTools::CppModelManagerInterface *cppMM = CppTools::CppModelManagerInterface::instance(); @@ -148,9 +148,11 @@ QVariant TestTreeModel::data(const QModelIndex &index, int role) const if (role == Qt::DisplayRole) { if ((item == m_autoTestRootItem && m_autoTestRootItem->childCount() == 0) - /*|| (item == m_quickTestRootItem && m_quickTestRootItem->childCount() == 0)*/) { + || (item == m_quickTestRootItem && m_quickTestRootItem->childCount() == 0)) { return QString(item->name() + tr(" (none)")); } else { + if (item->name().isEmpty()) + return tr(""); return item->name(); } @@ -158,6 +160,10 @@ QVariant TestTreeModel::data(const QModelIndex &index, int role) const } switch(role) { case Qt::ToolTipRole: + if (item->type() == TestTreeItem::TEST_CLASS && item->name().isEmpty()) + return tr("

Unnamed test cases can't be (un)checked - avoid this by assigning a name." + "
Having unnamed test cases invalidates the check state of named test " + "cases with the same main.cpp when executing selected tests.

"); return item->filePath(); case Qt::DecorationRole: return testTreeIcon(item->type()); @@ -214,8 +220,12 @@ Qt::ItemFlags TestTreeModel::flags(const QModelIndex &index) const TestTreeItem *item = static_cast(index.internalPointer()); switch(item->type()) { case TestTreeItem::TEST_CLASS: + if (item->name().isEmpty()) + return Qt::ItemIsSelectable | Qt::ItemIsTristate; return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsTristate | Qt::ItemIsUserCheckable; case TestTreeItem::TEST_FUNCTION: + if (item->parent()->name().isEmpty()) + return Qt::ItemIsSelectable; return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable; case TestTreeItem::ROOT: default: @@ -245,7 +255,7 @@ bool TestTreeModel::removeRows(int row, int count, const QModelIndex &parent) bool TestTreeModel::hasTests() const { - return m_autoTestRootItem->childCount() > 0 /*|| m_quickTestRootItem->childCount() > 0*/; + return m_autoTestRootItem->childCount() > 0 || m_quickTestRootItem->childCount() > 0; } static void addProjectInformation(TestConfiguration *config, const QString &filePath) @@ -265,7 +275,7 @@ static void addProjectInformation(TestConfiguration *config, const QString &file if (project) { if (auto target = project->activeTarget()) { ProjectExplorer::BuildTargetInfoList appTargets = target->applicationTargets(); - foreach (ProjectExplorer::BuildTargetInfo bti, appTargets.list) { + foreach (const ProjectExplorer::BuildTargetInfo &bti, appTargets.list) { if (bti.isValid() && bti.projectFilePath.toString() == proFile) { targetFile = bti.targetFilePath.toString(); targetName = bti.targetName; @@ -301,15 +311,44 @@ QList TestTreeModel::getAllTestCases() const { QList result; - int count = m_autoTestRootItem->childCount(); - for (int row = 0; row < count; ++row) { - TestTreeItem *child = m_autoTestRootItem->child(row); + // get all Auto Tests + for (int row = 0, count = m_autoTestRootItem->childCount(); row < count; ++row) { + const TestTreeItem *child = m_autoTestRootItem->child(row); TestConfiguration *tc = new TestConfiguration(child->name(), QStringList(), child->childCount()); addProjectInformation(tc, child->filePath()); result << tc; } + + // get all Quick Tests + QMap foundMains; + for (int row = 0, count = m_quickTestRootItem->childCount(); row < count; ++row) { + TestTreeItem *child = m_quickTestRootItem->child(row); + // unnamed Quick Tests must be handled separately + if (child->name().isEmpty()) { + for (int childRow = 0, ccount = child->childCount(); childRow < ccount; ++ childRow) { + const TestTreeItem *grandChild = child->child(childRow); + const QString mainFile = grandChild->mainFile(); + foundMains.insert(mainFile, foundMains.contains(mainFile) + ? foundMains.value(mainFile) + 1 : 1); + } + continue; + } + // named Quick Test + const QString mainFile = child->mainFile(); + foundMains.insert(mainFile, foundMains.contains(mainFile) + ? foundMains.value(mainFile) + child->childCount() + : child->childCount()); + } + // create TestConfiguration for each main + foreach (const QString &mainFile, foundMains.keys()) { + TestConfiguration *tc = new TestConfiguration(QString(), QStringList(), + foundMains.value(mainFile)); + addProjectInformation(tc, mainFile); + result << tc; + } + return result; } @@ -318,8 +357,7 @@ QList TestTreeModel::getSelectedTests() const QList result; TestConfiguration *tc; - int count = m_autoTestRootItem->childCount(); - for (int row = 0; row < count; ++row) { + for (int row = 0, count = m_autoTestRootItem->childCount(); row < count; ++row) { TestTreeItem *child = m_autoTestRootItem->child(row); switch (child->checked()) { @@ -332,7 +370,7 @@ QList TestTreeModel::getSelectedTests() const continue; case Qt::PartiallyChecked: default: - QString childName = child->name(); + const QString childName = child->name(); int grandChildCount = child->childCount(); QStringList testCases; for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) { @@ -346,23 +384,186 @@ QList TestTreeModel::getSelectedTests() const result << tc; } } + // Quick Tests must be handled differently - need the calling cpp file to use this in + // addProjectInformation() - additionally this must be unique to not execute the same executable + // on and on and on... + // TODO: do this later on for Auto Tests as well to support strange setups? or redo the model + + QMap foundMains; + + TestTreeItem *unnamed = unnamedQuickTests(); + for (int childRow = 0, ccount = unnamed->childCount(); childRow < ccount; ++ childRow) { + const TestTreeItem *grandChild = unnamed->child(childRow); + const QString mainFile = grandChild->mainFile(); + if (foundMains.contains(mainFile)) { + foundMains[mainFile]->setTestCaseCount(tc->testCaseCount() + 1); + } else { + TestConfiguration *tc = new TestConfiguration(QString(), QStringList()); + tc->setTestCaseCount(1); + addProjectInformation(tc, mainFile); + foundMains.insert(mainFile, tc); + } + } + + for (int row = 0, count = m_quickTestRootItem->childCount(); row < count; ++row) { + TestTreeItem *child = m_quickTestRootItem->child(row); + // unnamed Quick Tests have been handled separately already + if (child->name().isEmpty()) + continue; + + // named Quick Tests + switch (child->checked()) { + case Qt::Unchecked: + continue; + case Qt::Checked: + case Qt::PartiallyChecked: + default: + QStringList testFunctions; + int grandChildCount = child->childCount(); + for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) { + const TestTreeItem *grandChild = child->child(grandChildRow); + if (grandChild->checked() == Qt::Checked) + testFunctions << child->name() + QLatin1String("::") + grandChild->name(); + } + TestConfiguration *tc; + if (foundMains.contains(child->mainFile())) { + tc = foundMains[child->mainFile()]; + QStringList oldFunctions(tc->testCases()); + // if oldFunctions.size() is 0 this test configuration is used for at least one + // unnamed test case + if (oldFunctions.size() == 0) { + tc->setTestCaseCount(tc->testCaseCount() + testFunctions.size()); + } else { + oldFunctions << testFunctions; + tc->setTestCases(oldFunctions); + } + } else { + tc = new TestConfiguration(QString(), testFunctions); + addProjectInformation(tc, child->mainFile()); + foundMains.insert(child->mainFile(), tc); + } + break; + } + } + + foreach (TestConfiguration *config, foundMains.values()) + result << config; + return result; } +TestTreeItem *TestTreeModel::unnamedQuickTests() const +{ + for (int row = 0, count = m_quickTestRootItem->childCount(); row < count; ++row) { + TestTreeItem *child = m_quickTestRootItem->child(row); + if (child->name().isEmpty()) + return child; + } + return 0; +} + void TestTreeModel::modifyAutoTestSubtree(int row, TestTreeItem *newItem) { - static QVector modificationRoles = QVector() << Qt::DisplayRole - << Qt::ToolTipRole << LinkRole; QModelIndex toBeModifiedIndex = index(0, 0).child(row, 0); + modifyTestSubtree(toBeModifiedIndex, newItem); +} + +void TestTreeModel::removeAutoTestSubtreeByFilePath(const QString &file) +{ + const QModelIndex atRootIndex = index(0, 0); + const int count = rowCount(atRootIndex); + for (int row = 0; row < count; ++row) { + const QModelIndex childIndex = atRootIndex.child(row, 0); + TestTreeItem *childItem = static_cast(childIndex.internalPointer()); + if (file == childItem->filePath()) { + removeRow(row, atRootIndex); + break; + } + } + emit testTreeModelChanged(); +} + +void TestTreeModel::addAutoTest(TestTreeItem *newItem) +{ + beginInsertRows(index(0, 0), m_autoTestRootItem->childCount(), m_autoTestRootItem->childCount()); + m_autoTestRootItem->appendChild(newItem); + endInsertRows(); + emit testTreeModelChanged(); +} + +void TestTreeModel::removeAllAutoTests() +{ + beginResetModel(); + m_autoTestRootItem->removeChildren(); + endResetModel(); + emit testTreeModelChanged(); +} + +void TestTreeModel::modifyQuickTestSubtree(int row, TestTreeItem *newItem) +{ + QModelIndex toBeModifiedIndex = index(1, 0).child(row, 0); + modifyTestSubtree(toBeModifiedIndex, newItem); +} + +void TestTreeModel::removeQuickTestSubtreeByFilePath(const QString &file) +{ + const QModelIndex qtRootIndex = index(1, 0); + for (int row = 0, count = rowCount(qtRootIndex); row < count; ++row) { + const QModelIndex childIndex = qtRootIndex.child(row, 0); + const TestTreeItem *childItem = static_cast(childIndex.internalPointer()); + if (file == childItem->filePath()) { + removeRow(row, qtRootIndex); + break; + } + } + emit testTreeModelChanged(); +} + +void TestTreeModel::addQuickTest(TestTreeItem *newItem) +{ + beginInsertRows(index(1, 0), m_quickTestRootItem->childCount(), m_quickTestRootItem->childCount()); + m_quickTestRootItem->appendChild(newItem); + endInsertRows(); + emit testTreeModelChanged(); +} + +void TestTreeModel::removeAllQuickTests() +{ + beginResetModel(); + m_quickTestRootItem->removeChildren(); + endResetModel(); + emit testTreeModelChanged(); +} + +void TestTreeModel::removeUnnamedQuickTest(const QString &filePath) +{ + TestTreeItem *unnamedQT = unnamedQuickTests(); + if (!unnamedQT) + return; + + const QModelIndex unnamedQTIndex = index(1, 0).child(unnamedQT->row(), 0); + for (int childRow = unnamedQT->childCount() - 1; childRow >= 0; --childRow) { + const TestTreeItem *child = unnamedQT->child(childRow); + if (filePath == child->filePath()) + removeRow(childRow, unnamedQTIndex); + } + emit testTreeModelChanged(); +} + +void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, TestTreeItem *newItem) +{ if (!toBeModifiedIndex.isValid()) return; + + static QVector modificationRoles = QVector() << Qt::DisplayRole + << Qt::ToolTipRole << LinkRole; TestTreeItem *toBeModifiedItem = static_cast(toBeModifiedIndex.internalPointer()); if (toBeModifiedItem->modifyContent(newItem)) emit dataChanged(toBeModifiedIndex, toBeModifiedIndex, modificationRoles); // process sub-items as well... - int childCount = toBeModifiedItem->childCount(); - int newChildCount = newItem->childCount(); + const int childCount = toBeModifiedItem->childCount(); + const int newChildCount = newItem->childCount(); // for keeping the CheckState on modifications QHash originalItems; @@ -427,36 +628,5 @@ void TestTreeModel::modifyAutoTestSubtree(int row, TestTreeItem *newItem) emit testTreeModelChanged(); } -void TestTreeModel::removeAutoTestSubtreeByFilePath(const QString &file) -{ - QModelIndex atRootIndex = index(0, 0); - int count = rowCount(atRootIndex); - for (int row = 0; row < count; ++row) { - QModelIndex childIndex = atRootIndex.child(row, 0); - TestTreeItem *childItem = static_cast(childIndex.internalPointer()); - if (file == childItem->filePath()) { - removeRow(row, atRootIndex); - break; - } - } - emit testTreeModelChanged(); -} - -void TestTreeModel::addAutoTest(TestTreeItem *newItem) -{ - beginInsertRows(index(0, 0), m_autoTestRootItem->childCount(), m_autoTestRootItem->childCount()); - m_autoTestRootItem->appendChild(newItem); - endInsertRows(); - emit testTreeModelChanged(); -} - -void TestTreeModel::removeAllAutoTests() -{ - beginResetModel(); - m_autoTestRootItem->removeChildren(); - endResetModel(); - emit testTreeModelChanged(); -} - } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 0a07ef0e3a1..72ecf88ff42 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -60,11 +60,19 @@ public: bool hasTests() const; QList getAllTestCases() const; QList getSelectedTests() const; + TestTreeItem *unnamedQuickTests() const; void modifyAutoTestSubtree(int row, TestTreeItem *newItem); void removeAutoTestSubtreeByFilePath(const QString &file); void addAutoTest(TestTreeItem *newItem); void removeAllAutoTests(); + + void modifyQuickTestSubtree(int row, TestTreeItem *newItem); + void removeQuickTestSubtreeByFilePath(const QString &file); + void addQuickTest(TestTreeItem *newItem); + void removeAllQuickTests(); + void removeUnnamedQuickTest(const QString &filePath); + signals: void testTreeModelChanged(); @@ -72,10 +80,11 @@ public slots: private: explicit TestTreeModel(QObject *parent = 0); + void modifyTestSubtree(QModelIndex &toBeModifiedIndex, TestTreeItem *newItem); TestTreeItem *m_rootItem; TestTreeItem *m_autoTestRootItem; -// TestTreeItem *m_quickTestRootItem; + TestTreeItem *m_quickTestRootItem; TestCodeParser *m_parser; }; diff --git a/plugins/autotest/testtreeview.cpp b/plugins/autotest/testtreeview.cpp index 73d0fbbbd9e..37739832897 100644 --- a/plugins/autotest/testtreeview.cpp +++ b/plugins/autotest/testtreeview.cpp @@ -32,6 +32,8 @@ #include #include +#include + #include #include @@ -61,11 +63,16 @@ TestTreeViewWidget::TestTreeViewWidget(QWidget *parent) : CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); connect(cppMM, &CppTools::CppModelManager::documentUpdated, - parser, &TestCodeParser::onDocumentUpdated, Qt::QueuedConnection); - + parser, &TestCodeParser::onCppDocumentUpdated, Qt::QueuedConnection); connect(cppMM, &CppTools::CppModelManager::aboutToRemoveFiles, parser, &TestCodeParser::removeFiles, Qt::QueuedConnection); + QmlJS::ModelManagerInterface *qmlJsMM = QmlJSTools::Internal::ModelManager::instance(); + connect(qmlJsMM, &QmlJS::ModelManagerInterface::documentUpdated, + parser, &TestCodeParser::onQmlDocumentUpdated, Qt::QueuedConnection); + connect(qmlJsMM, &QmlJS::ModelManagerInterface::aboutToRemoveFiles, + parser, &TestCodeParser::removeFiles, Qt::QueuedConnection); + connect(m_view, &TestTreeView::activated, this, &TestTreeViewWidget::onItemActivated); } @@ -208,28 +215,32 @@ void TestTreeView::deselectAll() void TestTreeView::selectOrDeselectAll(const Qt::CheckState checkState) { const TestTreeModel *model = TestTreeModel::instance(); - QModelIndex autoTestsIndex = model->index(0, 0, rootIndex()); - if (!autoTestsIndex.isValid()) - return; - int count = model->rowCount(autoTestsIndex); - QModelIndex last; - for (int i = 0; i < count; ++i) { - const QModelIndex classesIndex = model->index(i, 0, autoTestsIndex); - int funcCount = model->rowCount(classesIndex); - TestTreeItem *item = static_cast(classesIndex.internalPointer()); - if (item) { - item->setChecked(checkState); - if (!item->childCount()) - last = classesIndex; - } - for (int j = 0; j < funcCount; ++j) { - last = model->index(j, 0, classesIndex); - TestTreeItem *item = static_cast(last.internalPointer()); - if (item) + + // 2 == Auto Tests and Quick Tests - must be raised if there will be others + for (int rootRow = 0; rootRow < 2; ++rootRow) { + QModelIndex currentRootIndex = model->index(rootRow, 0, rootIndex()); + if (!currentRootIndex.isValid()) + return; + int count = model->rowCount(currentRootIndex); + QModelIndex last; + for (int classesRow = 0; classesRow < count; ++classesRow) { + const QModelIndex classesIndex = model->index(classesRow, 0, currentRootIndex); + int funcCount = model->rowCount(classesIndex); + TestTreeItem *item = static_cast(classesIndex.internalPointer()); + if (item) { item->setChecked(checkState); + if (!item->childCount()) + last = classesIndex; + } + for (int functionRow = 0; functionRow < funcCount; ++functionRow) { + last = model->index(functionRow, 0, classesIndex); + TestTreeItem *item = static_cast(last.internalPointer()); + if (item) + item->setChecked(checkState); + } } + emit dataChanged(currentRootIndex, last); } - emit dataChanged(autoTestsIndex, last); } } // namespace Internal diff --git a/plugins/autotest/testvisitor.cpp b/plugins/autotest/testvisitor.cpp index e1c4fda65b3..199f3236b22 100644 --- a/plugins/autotest/testvisitor.cpp +++ b/plugins/autotest/testvisitor.cpp @@ -26,11 +26,15 @@ #include +#include + #include namespace Autotest { namespace Internal { +/************************** Cpp Test Symbol Visitor ***************************/ + TestVisitor::TestVisitor(const QString &fullQualifiedClassName) : m_className(fullQualifiedClassName) { @@ -59,10 +63,11 @@ bool TestVisitor::visit(CPlusPlus::Class *symbol) if (className != m_className) continue; - if (auto func = type->asFunctionType()) { + if (const auto func = type->asFunctionType()) { if (func->isSlot() && member->isPrivate()) { const QString name = o.prettyName(func->name()); if (!ignoredFunctions.contains(name) && !name.endsWith(QLatin1String("_data"))) { + // TODO use definition of function instead of declaration! TestCodeLocation location; location.m_fileName = QLatin1String(member->fileName()); location.m_line = member->line(); @@ -75,6 +80,8 @@ bool TestVisitor::visit(CPlusPlus::Class *symbol) return true; } +/**************************** Cpp Test AST Visitor ****************************/ + TestAstVisitor::TestAstVisitor(CPlusPlus::Document::Ptr doc) : ASTVisitor(doc->translationUnit()), m_currentDoc(doc) @@ -90,15 +97,15 @@ bool TestAstVisitor::visit(CPlusPlus::CallAST *ast) if (!m_currentScope || m_currentDoc.isNull()) return false; - if (auto expressionAST = ast->base_expression) { - if (auto idExpressionAST = expressionAST->asIdExpression()) { - if (auto qualifiedNameAST = idExpressionAST->name->asQualifiedName()) { + if (const auto expressionAST = ast->base_expression) { + if (const auto idExpressionAST = expressionAST->asIdExpression()) { + if (const auto qualifiedNameAST = idExpressionAST->name->asQualifiedName()) { const CPlusPlus::Overview o; const QString prettyName = o.prettyName(qualifiedNameAST->name); if (prettyName == QLatin1String("QTest::qExec")) { - if (auto expressionListAST = ast->expression_list) { + if (const auto expressionListAST = ast->expression_list) { // first argument is the one we need - if (auto argumentExpressionAST = expressionListAST->value) { + if (const auto argumentExpressionAST = expressionListAST->value) { CPlusPlus::TypeOfExpression toe; CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); toe.init(m_currentDoc, cppMM->snapshot()); @@ -106,7 +113,7 @@ bool TestAstVisitor::visit(CPlusPlus::CallAST *ast) = toe(argumentExpressionAST, m_currentDoc, m_currentScope); if (toeItems.size()) { - if (auto pointerType = toeItems.first().type()->asPointerType()) + if (const auto pointerType = toeItems.first().type()->asPointerType()) m_className = o.prettyType(pointerType->elementType()); } } @@ -124,5 +131,63 @@ bool TestAstVisitor::visit(CPlusPlus::CompoundStatementAST *ast) return true; } +/*************************** Quick Test AST Visitor ***************************/ + +TestQmlVisitor::TestQmlVisitor(QmlJS::Document::Ptr doc) + : m_currentDoc(doc) +{ +} + +TestQmlVisitor::~TestQmlVisitor() +{ +} + +bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast) +{ + const QStringRef name = ast->qualifiedTypeNameId->name; + if (name != QLatin1String("TestCase")) + return false; + + m_currentTestCaseName.clear(); + const auto sourceLocation = ast->firstSourceLocation(); + m_testCaseLocation.m_fileName = m_currentDoc->fileName(); + m_testCaseLocation.m_line = sourceLocation.startLine; + m_testCaseLocation.m_column = sourceLocation.startColumn - 1; + return true; +} + +bool TestQmlVisitor::visit(QmlJS::AST::ExpressionStatement *ast) +{ + const QmlJS::AST::ExpressionNode *expr = ast->expression; + return expr->kind == QmlJS::AST::Node::Kind_StringLiteral; +} + +bool TestQmlVisitor::visit(QmlJS::AST::UiScriptBinding *ast) +{ + const QStringRef name = ast->qualifiedId->name; + return name == QLatin1String("name"); +} + +bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast) +{ + const QStringRef name = ast->name; + if (name.startsWith(QLatin1String("test_"))) { + const auto sourceLocation = ast->firstSourceLocation(); + TestCodeLocation location; + location.m_fileName = m_currentDoc->fileName(); + location.m_line = sourceLocation.startLine; + location.m_column = sourceLocation.startColumn - 1; + + m_testFunctions.insert(name.toString(), location); + } + return false; +} + +bool TestQmlVisitor::visit(QmlJS::AST::StringLiteral *ast) +{ + m_currentTestCaseName = ast->value.toString(); + return false; +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testvisitor.h b/plugins/autotest/testvisitor.h index 04076cf80c5..92bfa009aea 100644 --- a/plugins/autotest/testvisitor.h +++ b/plugins/autotest/testvisitor.h @@ -24,6 +24,9 @@ #include #include +#include +#include + #include #include @@ -69,6 +72,30 @@ private: }; +class TestQmlVisitor : public QmlJS::AST::Visitor +{ +public: + TestQmlVisitor(QmlJS::Document::Ptr doc); + virtual ~TestQmlVisitor(); + + bool visit(QmlJS::AST::UiObjectDefinition *ast); + bool visit(QmlJS::AST::ExpressionStatement *ast); + bool visit(QmlJS::AST::UiScriptBinding *ast); + bool visit(QmlJS::AST::FunctionDeclaration *ast); + bool visit(QmlJS::AST::StringLiteral *ast); + + QString testCaseName() const { return m_currentTestCaseName; } + TestCodeLocation testCaseLocation() const { return m_testCaseLocation; } + QMap testFunctions() const { return m_testFunctions; } + +private: + QmlJS::Document::Ptr m_currentDoc; + QString m_currentTestCaseName; + TestCodeLocation m_testCaseLocation; + QMap m_testFunctions; + +}; + } // namespace Internal } // namespace Autotest From 9a644d1257199a58cbb208c79c33831458d4aa01 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 11 Nov 2014 17:30:34 +0100 Subject: [PATCH 017/200] Support sorting of test tree Additionally preparation of filtering has been done. --- plugins/autotest/autotestconstants.h | 3 + plugins/autotest/testcodeparser.cpp | 109 +++++++++++++++----------- plugins/autotest/testresult.cpp | 80 ++++++++++++++----- plugins/autotest/testresult.h | 1 + plugins/autotest/testresultspane.cpp | 4 +- plugins/autotest/testtreeitem.cpp | 17 ++++ plugins/autotest/testtreeitem.h | 2 + plugins/autotest/testtreemodel.cpp | 112 +++++++++++++++++++++++++-- plugins/autotest/testtreemodel.h | 36 ++++++++- plugins/autotest/testtreeview.cpp | 48 ++++++++++-- plugins/autotest/testtreeview.h | 9 +++ 11 files changed, 341 insertions(+), 80 deletions(-) diff --git a/plugins/autotest/autotestconstants.h b/plugins/autotest/autotestconstants.h index 3cfc770d45d..a4f6bdc7d9f 100644 --- a/plugins/autotest/autotestconstants.h +++ b/plugins/autotest/autotestconstants.h @@ -19,6 +19,8 @@ #ifndef AUTOTESTCONSTANTS_H #define AUTOTESTCONSTANTS_H +#include + namespace Autotest { namespace Constants { @@ -27,6 +29,7 @@ const char MENU_ID[] = "AutoTest.Menu"; const char AUTOTEST_ID[] = "AutoTest.ATP"; const char AUTOTEST_CONTEXT[] = "Auto Tests"; const char TASK_INDEX[] = "AutoTest.Task.Index"; +const char UNNAMED_QUICKTESTS[] = QT_TR_NOOP(""); } // namespace Autotest } // namespace Constants diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index f58b2a44891..9d4f41af06a 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -16,6 +16,7 @@ ** ****************************************************************************/ +#include "autotestconstants.h" #include "testcodeparser.h" #include "testinfo.h" #include "testtreeitem.h" @@ -385,51 +386,60 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr doc) m_model->removeQuickTestSubtreeByFilePath(d->fileName()); m_quickDocMap.remove(d->fileName()); } - bool hadUnnamedTestsBefore; - TestTreeItem *ttItem = m_model->unnamedQuickTests(); - if (!ttItem) { - hadUnnamedTestsBefore = false; - ttItem = new TestTreeItem(QString(), QString(), TestTreeItem::TEST_CLASS, - quickTestRootItem); - foreach (const QString &func, testFunctions.keys()) { - const TestCodeLocation location = testFunctions.value(func); - TestTreeItem *ttSub = new TestTreeItem(func, location.m_fileName, - TestTreeItem::TEST_FUNCTION, ttItem); - ttSub->setLine(location.m_line); - ttSub->setColumn(location.m_column); - ttSub->setMainFile(doc->fileName()); - ttItem->appendChild(ttSub); - } - } else { - hadUnnamedTestsBefore = true; + TestTreeItem *unnamedQTItem = m_model->unnamedQuickTests(); + if (unnamedQTItem) { // remove unnamed quick tests that are already found for this qml file - m_model->removeUnnamedQuickTest(d->fileName()); - - foreach (const QString &func, testFunctions.keys()) { - const TestCodeLocation location = testFunctions.value(func); - TestTreeItem *ttSub = new TestTreeItem(func, location.m_fileName, - TestTreeItem::TEST_FUNCTION, ttItem); - ttSub->setLine(location.m_line); - ttSub->setColumn(location.m_column); - ttSub->setMainFile(doc->fileName()); - ttItem->appendChild(ttSub); + if (m_model->removeUnnamedQuickTests(d->fileName())) { + // make sure m_quickDocMap does not have a inconsistent state now + TestInfo ti = m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)]; + QStringList tiFunctions = ti.testFunctions(); + foreach (const QString &func, testFunctions.keys()) + tiFunctions.removeOne(func); + ti.setTestFunctions(tiFunctions); + if (tiFunctions.size() == 0) + m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); + else + m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), ti); + } + // as removeUnnamedQuickTests() could delete this item itself try to get it again + unnamedQTItem = m_model->unnamedQuickTests(); + } + // construct new/modified TestTreeItem + TestTreeItem *ttItem = new TestTreeItem(QString(), QString(), + TestTreeItem::TEST_CLASS, + quickTestRootItem); + if (unnamedQTItem) { + for (int i = 0, count = unnamedQTItem->childCount(); i < count; ++i) { + TestTreeItem *child = new TestTreeItem(*unnamedQTItem->child(i)); + child->setParent(ttItem); + ttItem->appendChild(child); } } - TestInfo info = m_quickDocMap.contains(QLatin1String("")) - ? m_quickDocMap[QLatin1String("")] + + foreach (const QString &func, testFunctions.keys()) { + const TestCodeLocation location = testFunctions.value(func); + TestTreeItem *ttSub = new TestTreeItem(func, location.m_fileName, + TestTreeItem::TEST_FUNCTION, ttItem); + ttSub->setLine(location.m_line); + ttSub->setColumn(location.m_column); + ttSub->setMainFile(doc->fileName()); + ttItem->appendChild(ttSub); + } + TestInfo info = m_quickDocMap.contains(tr(Constants::UNNAMED_QUICKTESTS)) + ? m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)] : TestInfo(QString(), QStringList(), 666); QStringList originalFunctions(info.testFunctions()); - foreach (const QString &func, testFunctions.keys()) { - if (!originalFunctions.contains(func)) - originalFunctions.append(func); - } + foreach (const QString &func, testFunctions.keys()) + originalFunctions.append(func); info.setTestFunctions(originalFunctions); - if (hadUnnamedTestsBefore) - m_model->modifyQuickTestSubtree(ttItem->row(), ttItem); - else + if (unnamedQTItem) { + m_model->modifyQuickTestSubtree(unnamedQTItem->row(), ttItem); + delete ttItem; + } else { m_model->addQuickTest(ttItem); - m_quickDocMap.insert(QLatin1String(""), info); + } + m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), info); continue; } // end of handling test cases without name property @@ -468,15 +478,20 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr doc) delete ttItem; } else { // if it was formerly unnamed remove the respective items - if (m_quickDocMap.contains(QLatin1String(""))) { - m_model->removeUnnamedQuickTest(d->fileName()); - TestInfo unnamedInfo = m_quickDocMap[QLatin1String("")]; - QStringList functions = unnamedInfo.testFunctions(); - foreach (const QString &func, testFunctions.keys()) - if (functions.contains(func)) - functions.removeOne(func); - unnamedInfo.setTestFunctions(functions); - m_quickDocMap.insert(QLatin1String(""), unnamedInfo); + if (m_quickDocMap.contains(tr(Constants::UNNAMED_QUICKTESTS))) { + if (m_model->removeUnnamedQuickTests(d->fileName())) { + // make sure m_quickDocMap does not have a inconsistent state now + TestInfo unnamedInfo = m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)]; + QStringList functions = unnamedInfo.testFunctions(); + foreach (const QString &func, testFunctions.keys()) + if (functions.contains(func)) + functions.removeOne(func); + unnamedInfo.setTestFunctions(functions); + if (functions.size() == 0) + m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); + else + m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), unnamedInfo); + } } m_model->addQuickTest(ttItem); @@ -523,7 +538,7 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &doc) && snapshot.contains(m_quickDocMap[fileName].referencingFile())) { checkDocumentForTestCode(snapshot.document(m_quickDocMap[fileName].referencingFile())); } - if (!m_quickDocMap.contains(QLatin1String(""))) + if (!m_quickDocMap.contains(tr(Constants::UNNAMED_QUICKTESTS))) return; // special case of having unnamed TestCases diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp index c75ba31ac6f..e3b974113be 100644 --- a/plugins/autotest/testresult.cpp +++ b/plugins/autotest/testresult.cpp @@ -55,18 +55,53 @@ ResultType TestResult::resultFromString(const QString &resultString) return UNKNOWN; } +ResultType TestResult::toResultType(int rt) +{ + switch(rt) { + case PASS: + return PASS; + case FAIL: + return FAIL; + case EXPECTED_FAIL: + return EXPECTED_FAIL; + case UNEXPECTED_PASS: + return UNEXPECTED_PASS; + case SKIP: + return SKIP; + case MESSAGE_DEBUG: + return MESSAGE_DEBUG; + case MESSAGE_WARN: + return MESSAGE_WARN; + case MESSAGE_FATAL: + return MESSAGE_FATAL; + case MESSAGE_INTERNAL: + return MESSAGE_INTERNAL; + default: + return UNKNOWN; + } +} + QString TestResult::resultToString(const ResultType type) { switch(type) { - case PASS: return QLatin1String("PASS"); - case FAIL: return QLatin1String("FAIL"); - case EXPECTED_FAIL: return QLatin1String("XFAIL"); - case UNEXPECTED_PASS: return QLatin1String("XPASS"); - case SKIP: return QLatin1String("SKIP"); - case MESSAGE_DEBUG: return QLatin1String("DEBUG"); - case MESSAGE_WARN: return QLatin1String("WARN"); - case MESSAGE_FATAL: return QLatin1String("FATAL"); - case MESSAGE_INTERNAL: return QString(); + case PASS: + return QLatin1String("PASS"); + case FAIL: + return QLatin1String("FAIL"); + case EXPECTED_FAIL: + return QLatin1String("XFAIL"); + case UNEXPECTED_PASS: + return QLatin1String("XPASS"); + case SKIP: + return QLatin1String("SKIP"); + case MESSAGE_DEBUG: + return QLatin1String("DEBUG"); + case MESSAGE_WARN: + return QLatin1String("WARN"); + case MESSAGE_FATAL: + return QLatin1String("FATAL"); + case MESSAGE_INTERNAL: + return QString(); default: return QLatin1String("UNKNOWN"); } @@ -75,15 +110,24 @@ QString TestResult::resultToString(const ResultType type) QColor TestResult::colorForType(const ResultType type) { switch(type) { - case PASS: return QColor("#009900"); - case FAIL: return QColor("#a00000"); - case EXPECTED_FAIL: return QColor("#00ff00"); - case UNEXPECTED_PASS: return QColor("#ff0000"); - case SKIP: return QColor("#787878"); - case MESSAGE_DEBUG: return QColor("#329696"); - case MESSAGE_WARN: return QColor("#d0bb00"); - case MESSAGE_FATAL: return QColor("#640000"); - case MESSAGE_INTERNAL: return QColor("transparent"); + case PASS: + return QColor("#009900"); + case FAIL: + return QColor("#a00000"); + case EXPECTED_FAIL: + return QColor("#00ff00"); + case UNEXPECTED_PASS: + return QColor("#ff0000"); + case SKIP: + return QColor("#787878"); + case MESSAGE_DEBUG: + return QColor("#329696"); + case MESSAGE_WARN: + return QColor("#d0bb00"); + case MESSAGE_FATAL: + return QColor("#640000"); + case MESSAGE_INTERNAL: + return QColor("transparent"); default: return QColor("#000000"); } diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index b8b6a2dd1a6..aa0d01e4e7c 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -57,6 +57,7 @@ public: void setLine(int line) { m_line = line; } static ResultType resultFromString(const QString &resultString); + static ResultType toResultType(int rt); static QString resultToString(const ResultType type); static QColor colorForType(const ResultType type); diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 06a3257b0a1..e9d0f1be561 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -322,7 +322,7 @@ void TestResultsPane::updateFilterMenu() foreach (QAction *action, m_filterMenu->actions()) { if (action->isCheckable()) action->setEnabled(m_model->hasResultType( - static_cast(action->data().value()))); + TestResult::toResultType(action->data().value()))); } } @@ -337,7 +337,7 @@ void TestResultsPane::enableAllFilter() void TestResultsPane::filterMenuTriggered(QAction *action) { - m_filterModel->toggleTestResultType(static_cast(action->data().value())); + m_filterModel->toggleTestResultType(TestResult::toResultType(action->data().value())); navigateStateChanged(); } diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index 3b7c27fcde4..5ffd1927613 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -36,6 +36,23 @@ TestTreeItem::~TestTreeItem() removeChildren(); } +TestTreeItem::TestTreeItem(const TestTreeItem &other) + : m_name(other.m_name), + m_filePath(other.m_filePath), + m_checked(other.m_checked), + m_type(other.m_type), + m_line(other.m_line), + m_column(other.m_column), + m_mainFile(other.m_mainFile), + m_parent(other.m_parent) +{ + foreach (const TestTreeItem *child, other.m_children) { + TestTreeItem *reparentedChild = new TestTreeItem(*child); + reparentedChild->m_parent = this; + m_children.append(reparentedChild); + } +} + TestTreeItem *TestTreeItem::child(int row) { return m_children.at(row); diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index eaa1d68656c..6f0ca88e2d0 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -35,6 +35,7 @@ public: TestTreeItem(const QString &name, const QString &filePath, Type type, TestTreeItem *parent = 0); virtual ~TestTreeItem(); + TestTreeItem(const TestTreeItem& other); TestTreeItem *child(int row); TestTreeItem *parent() const; @@ -58,6 +59,7 @@ public: void setChecked(const Qt::CheckState checked); Qt::CheckState checked() const { return m_checked; } Type type() const { return m_type; } + void setParent(TestTreeItem *parent) { m_parent = parent; } private: void revalidateCheckState(); diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 38a38c51f93..93d9d160ef7 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -16,6 +16,7 @@ ** ****************************************************************************/ +#include "autotestconstants.h" #include "testcodeparser.h" #include "testtreeitem.h" #include "testtreemodel.h" @@ -152,7 +153,7 @@ QVariant TestTreeModel::data(const QModelIndex &index, int role) const return QString(item->name() + tr(" (none)")); } else { if (item->name().isEmpty()) - return tr(""); + return tr(Constants::UNNAMED_QUICKTESTS); return item->name(); } @@ -535,19 +536,24 @@ void TestTreeModel::removeAllQuickTests() emit testTreeModelChanged(); } -void TestTreeModel::removeUnnamedQuickTest(const QString &filePath) +bool TestTreeModel::removeUnnamedQuickTests(const QString &filePath) { TestTreeItem *unnamedQT = unnamedQuickTests(); if (!unnamedQT) - return; + return false; + bool removed = false; const QModelIndex unnamedQTIndex = index(1, 0).child(unnamedQT->row(), 0); for (int childRow = unnamedQT->childCount() - 1; childRow >= 0; --childRow) { const TestTreeItem *child = unnamedQT->child(childRow); if (filePath == child->filePath()) - removeRow(childRow, unnamedQTIndex); + removed |= removeRow(childRow, unnamedQTIndex); } + + if (unnamedQT->childCount() == 0) + removeRow(unnamedQT->row(), unnamedQTIndex.parent()); emit testTreeModelChanged(); + return removed; } void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, TestTreeItem *newItem) @@ -566,6 +572,7 @@ void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, TestTreeIt const int newChildCount = newItem->childCount(); // for keeping the CheckState on modifications + // TODO might still fail for duplicate entries (e.g. unnamed Quick Tests) QHash originalItems; for (int row = 0; row < childCount; ++row) { const TestTreeItem *child = toBeModifiedItem->child(row); @@ -594,9 +601,8 @@ void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, TestTreeIt if (childCount < newChildCount) { // add aditional items for (int row = childCount; row < newChildCount; ++row) { TestTreeItem *newChild = newItem->child(row); - TestTreeItem *toBeAdded = new TestTreeItem(newChild->name(), newChild->filePath(), - newChild->type(), toBeModifiedItem); - toBeAdded->setLine(newChild->line()); + TestTreeItem *toBeAdded = new TestTreeItem(*newChild); + toBeAdded->setParent(toBeModifiedItem); beginInsertRows(toBeModifiedIndex, row, row); toBeModifiedItem->appendChild(toBeAdded); endInsertRows(); @@ -628,5 +634,97 @@ void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, TestTreeIt emit testTreeModelChanged(); } +/***************************** Sort/Filter Model **********************************/ + +TestTreeSortFilterModel::TestTreeSortFilterModel(TestTreeModel *sourceModel, QObject *parent) + : QSortFilterProxyModel(parent), + m_sourceModel(sourceModel), + m_sortMode(Alphabetically), + m_filterMode(Basic) +{ + setSourceModel(sourceModel); +} + +void TestTreeSortFilterModel::setSortMode(SortMode sortMode) +{ + m_sortMode = sortMode; + invalidate(); +} + +void TestTreeSortFilterModel::setFilterMode(FilterMode filterMode) +{ + m_filterMode = filterMode; + invalidateFilter(); +} + +void TestTreeSortFilterModel::toggleFilter(FilterMode filterMode) +{ + m_filterMode = toFilterMode(m_filterMode ^ filterMode); + invalidateFilter(); +} + +TestTreeSortFilterModel::FilterMode TestTreeSortFilterModel::toFilterMode(int f) +{ + switch (f) { + case TestTreeSortFilterModel::ShowInitAndCleanup: + return TestTreeSortFilterModel::ShowInitAndCleanup; + case TestTreeSortFilterModel::ShowTestData: + return TestTreeSortFilterModel::ShowTestData; + case TestTreeSortFilterModel::ShowAll: + return TestTreeSortFilterModel::ShowAll; + default: + return TestTreeSortFilterModel::Basic; + } +} + +bool TestTreeSortFilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const +{ + // root items keep the intended order: 1st Auto Tests, 2nd Quick Tests + const TestTreeItem *leftItem = static_cast(left.internalPointer()); + if (leftItem->type() == TestTreeItem::ROOT) + return left.row() > right.row(); + + const QString leftVal = m_sourceModel->data(left).toString(); + const QString rightVal = m_sourceModel->data(right).toString(); + + // unnamed Quick Tests will always be listed first + if (leftVal == tr(Constants::UNNAMED_QUICKTESTS)) + return false; + if (rightVal == tr(Constants::UNNAMED_QUICKTESTS)) + return true; + + switch (m_sortMode) { + case Alphabetically: + return leftVal > rightVal; + case Naturally: { + const TextEditor::TextEditorWidget::Link leftLink = + m_sourceModel->data(left, LinkRole).value(); + const TextEditor::TextEditorWidget::Link rightLink = + m_sourceModel->data(right, LinkRole).value(); + + if (leftLink.targetFileName == rightLink.targetFileName) { + return leftLink.targetLine == rightLink.targetLine + ? leftLink.targetColumn > rightLink.targetColumn + : leftLink.targetLine > rightLink.targetLine; + } else { + return leftLink.targetFileName > rightLink.targetFileName; + } + } + default: + return true; + } +} + +bool TestTreeSortFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + // TODO add filtering capabilities + QModelIndex index = m_sourceModel->index(sourceRow, 0,sourceParent); + if (!index.isValid()) + return false; + + + return true; +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 72ecf88ff42..94cb874f8e5 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -24,6 +24,7 @@ #include #include +#include namespace { enum ItemRole { @@ -71,7 +72,7 @@ public: void removeQuickTestSubtreeByFilePath(const QString &file); void addQuickTest(TestTreeItem *newItem); void removeAllQuickTests(); - void removeUnnamedQuickTest(const QString &filePath); + bool removeUnnamedQuickTests(const QString &filePath); signals: void testTreeModelChanged(); @@ -89,6 +90,39 @@ private: }; +class TestTreeSortFilterModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + enum SortMode { + Alphabetically, + Naturally + }; + + enum FilterMode { + Basic, + ShowInitAndCleanup = 0x01, + ShowTestData = 0x02, + ShowAll = ShowInitAndCleanup | ShowTestData + }; + + TestTreeSortFilterModel(TestTreeModel *sourceModel, QObject *parent = 0); + void setSortMode(SortMode sortMode); + void setFilterMode(FilterMode filterMode); + void toggleFilter(FilterMode filterMode); + static FilterMode toFilterMode(int f); + +protected: + bool lessThan(const QModelIndex &left, const QModelIndex &right) const; + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; + +private: + TestTreeModel *m_sourceModel; + SortMode m_sortMode; + FilterMode m_filterMode; + +}; + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testtreeview.cpp b/plugins/autotest/testtreeview.cpp index 37739832897..45376db3830 100644 --- a/plugins/autotest/testtreeview.cpp +++ b/plugins/autotest/testtreeview.cpp @@ -23,6 +23,7 @@ #include "testtreemodel.h" #include "testtreeview.h" +#include #include #include @@ -47,8 +48,11 @@ TestTreeViewWidget::TestTreeViewWidget(QWidget *parent) : { setWindowTitle(tr("Tests")); m_model = TestTreeModel::instance(); + m_sortFilterModel = new TestTreeSortFilterModel(m_model, m_model); + m_sortFilterModel->setDynamicSortFilter(true); m_view = new TestTreeView(this); - m_view->setModel(m_model); + m_view->setModel(m_sortFilterModel); + m_view->setSortingEnabled(true); QVBoxLayout *layout = new QVBoxLayout; layout->setMargin(0); @@ -116,10 +120,21 @@ QList TestTreeViewWidget::createToolButtons() { QList list; + m_filterButton = new QToolButton(m_view); + m_filterButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_FILTER))); + m_filterButton->setToolTip(tr("Filter Test Tree")); + m_filterButton->setProperty("noArrow", true); + m_filterButton->setAutoRaise(true); + m_filterButton->setPopupMode(QToolButton::InstantPopup); + m_filterMenu = new QMenu(m_filterButton); + initializeFilterMenu(); + connect(m_filterMenu, &QMenu::triggered, this, &TestTreeViewWidget::onFilterMenuTriggered); + m_filterButton->setMenu(m_filterMenu); + m_sortAlphabetically = true; m_sort = new QToolButton(this); m_sort->setIcon((QIcon(QLatin1String(":/images/leafsort.png")))); - m_sort->setToolTip(tr("Sort Naturally (not implemented yet)")); + m_sort->setToolTip(tr("Sort Naturally")); QToolButton *expand = new QToolButton(this); expand->setIcon(QIcon(QLatin1String(":/images/expand.png"))); @@ -133,7 +148,7 @@ QList TestTreeViewWidget::createToolButtons() connect(collapse, &QToolButton::clicked, m_view, &TestTreeView::collapseAll); connect(m_sort, &QToolButton::clicked, this, &TestTreeViewWidget::onSortClicked); - list << m_sort << expand << collapse; + list << m_filterButton << m_sort << expand << collapse; return list; } @@ -167,14 +182,37 @@ void TestTreeViewWidget::onSortClicked() if (m_sortAlphabetically) { m_sort->setIcon((QIcon(QLatin1String(":/images/sort.png")))); m_sort->setToolTip(tr("Sort Alphabetically")); + m_sortFilterModel->setSortMode(TestTreeSortFilterModel::Naturally); } else { m_sort->setIcon((QIcon(QLatin1String(":/images/leafsort.png")))); - m_sort->setToolTip(tr("Sort Naturally (not implemented yet)")); + m_sort->setToolTip(tr("Sort Naturally")); + m_sortFilterModel->setSortMode(TestTreeSortFilterModel::Alphabetically); } - // TODO trigger the sorting change.. m_sortAlphabetically = !m_sortAlphabetically; } +void TestTreeViewWidget::onFilterMenuTriggered(QAction *action) +{ + m_sortFilterModel->toggleFilter( + TestTreeSortFilterModel::toFilterMode(action->data().value())); +} + +void TestTreeViewWidget::initializeFilterMenu() +{ + QAction *action = new QAction(m_filterMenu); + action->setText(tr("Show init and cleanup functions")); + action->setCheckable(true); + action->setChecked(false); + action->setData(TestTreeSortFilterModel::ShowInitAndCleanup); + m_filterMenu->addAction(action); + action = new QAction(m_filterMenu); + action->setText(tr("Show data functions")); + action->setCheckable(true); + action->setChecked(false); + action->setData(TestTreeSortFilterModel::ShowTestData); + m_filterMenu->addAction(action); +} + TestViewFactory::TestViewFactory() { setDisplayName(tr("Tests")); diff --git a/plugins/autotest/testtreeview.h b/plugins/autotest/testtreeview.h index 27e475f17c5..5f6c8670adf 100644 --- a/plugins/autotest/testtreeview.h +++ b/plugins/autotest/testtreeview.h @@ -24,6 +24,8 @@ #include QT_BEGIN_NAMESPACE +class QAction; +class QMenu; class QModelIndex; class QToolButton; QT_END_NAMESPACE @@ -36,6 +38,7 @@ namespace Autotest { namespace Internal { class TestTreeModel; +class TestTreeSortFilterModel; class TestTreeView : public Utils::NavigationTreeView { @@ -71,11 +74,17 @@ private slots: void onRunAllTriggered(); void onRunSelectedTriggered(); void onSortClicked(); + void onFilterMenuTriggered(QAction *action); private: + void initializeFilterMenu(); + TestTreeModel *m_model; + TestTreeSortFilterModel *m_sortFilterModel; TestTreeView *m_view; QToolButton *m_sort; + QToolButton *m_filterButton; + QMenu *m_filterMenu; bool m_sortAlphabetically; }; From b0c4a9cc3bbe6697692c07c31c96a2c937171364 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 13 Nov 2014 12:31:58 +0100 Subject: [PATCH 018/200] Improve support for Qt Quick Tests --- plugins/autotest/autotest.pro | 6 +- plugins/autotest/testcodeparser.cpp | 52 +++++---- plugins/autotest/testconfiguration.cpp | 5 + plugins/autotest/testconfiguration.h | 3 + plugins/autotest/testresultspane.cpp | 4 +- plugins/autotest/testrunner.cpp | 8 +- plugins/autotest/testtreeitem.cpp | 58 ++++++++-- plugins/autotest/testtreeitem.h | 8 +- plugins/autotest/testtreeitemdelegate.cpp | 69 +++++++++++ plugins/autotest/testtreeitemdelegate.h | 41 +++++++ plugins/autotest/testtreemodel.cpp | 132 +++++++++++++++++----- plugins/autotest/testtreemodel.h | 3 +- plugins/autotest/testtreeview.cpp | 2 + plugins/autotest/testvisitor.cpp | 36 +++--- plugins/autotest/testvisitor.h | 17 +-- 15 files changed, 353 insertions(+), 91 deletions(-) create mode 100644 plugins/autotest/testtreeitemdelegate.cpp create mode 100644 plugins/autotest/testtreeitemdelegate.h diff --git a/plugins/autotest/autotest.pro b/plugins/autotest/autotest.pro index 566c6131d12..6d2423bdd74 100644 --- a/plugins/autotest/autotest.pro +++ b/plugins/autotest/autotest.pro @@ -21,7 +21,8 @@ SOURCES += \ testresult.cpp \ testresultspane.cpp \ testresultmodel.cpp \ - testresultdelegate.cpp + testresultdelegate.cpp \ + testtreeitemdelegate.cpp HEADERS += \ testtreeview.h \ @@ -38,7 +39,8 @@ HEADERS += \ testresult.h \ testresultspane.h \ testresultmodel.h \ - testresultdelegate.h + testresultdelegate.h \ + testtreeitemdelegate.h RESOURCES += \ autotest.qrc diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 9d4f41af06a..240bb418d55 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -60,8 +60,10 @@ void TestCodeParser::updateTestTree() m_model->removeAllAutoTests(); m_model->removeAllQuickTests(); const ProjectExplorer::SessionManager *session = ProjectExplorer::SessionManager::instance(); - if (!session || !session->hasProjects()) + if (!session || !session->hasProjects()) { + m_currentProject = 0; return; + } m_currentProject = session->startupProject(); if (!m_currentProject) @@ -285,13 +287,13 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) } TestVisitor myVisitor(tc); myVisitor.accept(declaringDoc->globalNamespace()); - const QMap privSlots = myVisitor.privateSlots(); + const QMap privSlots = myVisitor.privateSlots(); foreach (const QString &privS, privSlots.keys()) { - const TestCodeLocation location = privSlots.value(privS); - TestTreeItem *ttSub = new TestTreeItem(privS, location.m_fileName, - TestTreeItem::TEST_FUNCTION, ttItem); - ttSub->setLine(location.m_line); - ttSub->setColumn(location.m_column); + const TestCodeLocationAndType locationAndType = privSlots.value(privS); + TestTreeItem *ttSub = new TestTreeItem(privS, locationAndType.m_fileName, + locationAndType.m_type, ttItem); + ttSub->setLine(locationAndType.m_line); + ttSub->setColumn(locationAndType.m_column); ttItem->appendChild(ttSub); } @@ -374,8 +376,8 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr doc) QmlJS::AST::Node::accept(ast, &qmlVisitor); const QString tcName = qmlVisitor.testCaseName(); - const TestCodeLocation tcLocation = qmlVisitor.testCaseLocation(); - const QMap testFunctions = qmlVisitor.testFunctions(); + const TestCodeLocationAndType tcLocationAndType = qmlVisitor.testCaseLocation(); + const QMap testFunctions = qmlVisitor.testFunctions(); const QModelIndex quickTestRootIndex = m_model->index(1, 0); TestTreeItem *quickTestRootItem = static_cast(quickTestRootIndex.internalPointer()); @@ -417,11 +419,11 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr doc) } foreach (const QString &func, testFunctions.keys()) { - const TestCodeLocation location = testFunctions.value(func); - TestTreeItem *ttSub = new TestTreeItem(func, location.m_fileName, - TestTreeItem::TEST_FUNCTION, ttItem); - ttSub->setLine(location.m_line); - ttSub->setColumn(location.m_column); + const TestCodeLocationAndType locationAndType = testFunctions.value(func); + TestTreeItem *ttSub = new TestTreeItem(func, locationAndType.m_fileName, + locationAndType.m_type, ttItem); + ttSub->setLine(locationAndType.m_line); + ttSub->setColumn(locationAndType.m_column); ttSub->setMainFile(doc->fileName()); ttItem->appendChild(ttSub); } @@ -445,23 +447,23 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr doc) } // end of handling test cases without name property // construct new/modified TestTreeItem - TestTreeItem *ttItem = new TestTreeItem(tcName, tcLocation.m_fileName, - TestTreeItem::TEST_CLASS, quickTestRootItem); - ttItem->setLine(tcLocation.m_line); - ttItem->setColumn(tcLocation.m_column); + TestTreeItem *ttItem = new TestTreeItem(tcName, tcLocationAndType.m_fileName, + tcLocationAndType.m_type, quickTestRootItem); + ttItem->setLine(tcLocationAndType.m_line); + ttItem->setColumn(tcLocationAndType.m_column); ttItem->setMainFile(doc->fileName()); foreach (const QString &func, testFunctions.keys()) { - const TestCodeLocation location = testFunctions.value(func); - TestTreeItem *ttSub = new TestTreeItem(func, location.m_fileName, - TestTreeItem::TEST_FUNCTION, ttItem); - ttSub->setLine(location.m_line); - ttSub->setColumn(location.m_column); + const TestCodeLocationAndType locationAndType = testFunctions.value(func); + TestTreeItem *ttSub = new TestTreeItem(func, locationAndType.m_fileName, + locationAndType.m_type, ttItem); + ttSub->setLine(locationAndType.m_line); + ttSub->setColumn(locationAndType.m_column); ttItem->appendChild(ttSub); } // update model and internal map - const QString fileName(tcLocation.m_fileName); + const QString fileName(tcLocationAndType.m_fileName); const QmlJS::Document::Ptr qmlDoc = QmlJSTools::Internal::ModelManager::instance()->snapshot().document(fileName); @@ -497,7 +499,7 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr doc) m_model->addQuickTest(ttItem); TestInfo ti(tcName, testFunctions.keys(), 0, qmlDoc->editorRevision()); ti.setReferencingFile(doc->fileName()); - m_quickDocMap.insert(tcLocation.m_fileName, ti); + m_quickDocMap.insert(tcLocationAndType.m_fileName, ti); } } } diff --git a/plugins/autotest/testconfiguration.cpp b/plugins/autotest/testconfiguration.cpp index bcb90d75b5e..73cdbdb918e 100644 --- a/plugins/autotest/testconfiguration.cpp +++ b/plugins/autotest/testconfiguration.cpp @@ -81,6 +81,11 @@ void TestConfiguration::setWorkingDirectory(const QString &workingDirectory) m_workingDir = workingDirectory; } +void TestConfiguration::setDisplayName(const QString &displayName) +{ + m_displayName = displayName; +} + void TestConfiguration::setEnvironment(const Utils::Environment &env) { m_environment = env; diff --git a/plugins/autotest/testconfiguration.h b/plugins/autotest/testconfiguration.h index aa82b8e2b53..54be3697aa0 100644 --- a/plugins/autotest/testconfiguration.h +++ b/plugins/autotest/testconfiguration.h @@ -46,6 +46,7 @@ public: void setTargetName(const QString &targetName); void setProFile(const QString &proFile); void setWorkingDirectory(const QString &workingDirectory); + void setDisplayName(const QString &displayName); void setEnvironment(const Utils::Environment &env); void setProject(ProjectExplorer::Project *project); @@ -56,6 +57,7 @@ public: QString targetFile() const { return m_targetFile; } QString targetName() const { return m_targetName; } QString workingDirectory() const { return m_workingDir; } + QString displayName() const { return m_displayName; } Utils::Environment environment() const { return m_environment; } ProjectExplorer::Project *project() const { return m_project; } @@ -72,6 +74,7 @@ private: QString m_targetFile; QString m_targetName; QString m_workingDir; + QString m_displayName; Utils::Environment m_environment; ProjectExplorer::Project *m_project; }; diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index e9d0f1be561..39441d90876 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -50,9 +50,9 @@ TestResultsPane::TestResultsPane(QObject *parent) : QPalette pal; pal.setColor(QPalette::Window, - Utils::creatorTheme()->color(Utils::Theme::SearchResultWidgetBackgroundColor)); + Utils::creatorTheme()->color(Utils::Theme::InfoBarBackground)); pal.setColor(QPalette::WindowText, - Utils::creatorTheme()->color(Utils::Theme::SearchResultWidgetTextColor)); + Utils::creatorTheme()->color(Utils::Theme::InfoBarText)); m_summaryWidget = new QFrame; m_summaryWidget->setPalette(pal); m_summaryWidget->setAutoFillBackground(true); diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index ed2383bb3f0..420360468bd 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -351,8 +351,14 @@ void TestRunner::runTests() } ProjectExplorer::Project *project = m_selectedTests.at(0)->project(); - if (!project) // add a warning or info to output? possible at all? + if (!project) { + TestResultsPane::instance()->addTestResult( + TestResult(QString(), QString(), QString(), ResultType::MESSAGE_WARN, + tr("*** Project is null - canceling Test Run ***\n" + "Actually only Desktop kits are supported - make sure the " + "current active kit is a Desktop kit."))); return; + } ProjectExplorer::ProjectExplorerPlugin *pep = ProjectExplorer::ProjectExplorerPlugin::instance(); ProjectExplorer::Internal::ProjectExplorerSettings pes = pep->projectExplorerSettings(); diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index 5ffd1927613..2da060da529 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -24,11 +24,29 @@ namespace Internal { TestTreeItem::TestTreeItem(const QString &name, const QString &filePath, Type type, TestTreeItem *parent) : m_name(name), m_filePath(filePath), - m_checked(type == ROOT ? Qt::Unchecked : Qt::Checked), m_type(type), m_line(0), m_parent(parent) { + switch (m_type) { + case ROOT: + m_checked = Qt::Unchecked; + break; + case TEST_CLASS: + case TEST_FUNCTION: + m_checked = Qt::Checked; + break; + case TEST_DATAFUNCTION: + case TEST_SPECIALFUNCTION: + if (m_parent) + m_checked = m_parent->checked() == Qt::PartiallyChecked ? Qt::Unchecked + : m_parent->checked(); + else + m_checked = Qt::Unchecked; + break; + default: + m_checked = Qt::Unchecked; + } } TestTreeItem::~TestTreeItem() @@ -121,19 +139,37 @@ bool TestTreeItem::modifyContent(const TestTreeItem *modified) void TestTreeItem::setChecked(const Qt::CheckState checkState) { switch (m_type) { - case ROOT: - return; - case TEST_FUNCTION: + case TEST_FUNCTION: { m_checked = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked); m_parent->revalidateCheckState(); break; - case TEST_CLASS: + } + case TEST_CLASS: { Qt::CheckState usedState = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked); foreach (TestTreeItem *child, m_children) { child->setChecked(usedState); } m_checked = usedState; } + default: + return; + } +} + +Qt::CheckState TestTreeItem::checked() const +{ + switch (m_type) { + case TEST_CLASS: + case TEST_FUNCTION: + return m_checked; + case TEST_DATAFUNCTION: + case TEST_SPECIALFUNCTION: + return m_parent->m_checked == Qt::PartiallyChecked ? Qt::Unchecked : m_parent->m_checked; + default: + if (m_parent) + return m_parent->m_checked; + } + return Qt::Unchecked; } void TestTreeItem::revalidateCheckState() @@ -143,8 +179,16 @@ void TestTreeItem::revalidateCheckState() bool foundChecked = false; bool foundUnchecked = false; foreach (const TestTreeItem *child, m_children) { - foundChecked |= (child->m_checked != Qt::Unchecked); - foundUnchecked |= (child->m_checked == Qt::Unchecked); + switch (child->type()) { + case TEST_DATAFUNCTION: + case TEST_SPECIALFUNCTION: + continue; + default: + break; + } + + foundChecked |= (child->checked() != Qt::Unchecked); + foundUnchecked |= (child->checked() == Qt::Unchecked); if (foundChecked && foundUnchecked) { m_checked = Qt::PartiallyChecked; return; diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index 6f0ca88e2d0..8ec916b0bf5 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -30,7 +30,11 @@ class TestTreeItem public: enum Type { - ROOT, TEST_CLASS, TEST_FUNCTION + ROOT, + TEST_CLASS, + TEST_FUNCTION, + TEST_DATAFUNCTION, + TEST_SPECIALFUNCTION }; TestTreeItem(const QString &name, const QString &filePath, Type type, TestTreeItem *parent = 0); @@ -57,7 +61,7 @@ public: QString mainFile() const { return m_mainFile; } void setMainFile(const QString &mainFile) { m_mainFile = mainFile; } void setChecked(const Qt::CheckState checked); - Qt::CheckState checked() const { return m_checked; } + Qt::CheckState checked() const; Type type() const { return m_type; } void setParent(TestTreeItem *parent) { m_parent = parent; } diff --git a/plugins/autotest/testtreeitemdelegate.cpp b/plugins/autotest/testtreeitemdelegate.cpp new file mode 100644 index 00000000000..71ccef57560 --- /dev/null +++ b/plugins/autotest/testtreeitemdelegate.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "testtreeitemdelegate.h" +#include "testtreemodel.h" + +#include + +namespace Autotest { +namespace Internal { + +TestTreeItemDelegate::TestTreeItemDelegate(QObject *parent) + : QStyledItemDelegate(parent) +{ +} + +TestTreeItemDelegate::~TestTreeItemDelegate() +{ +} + +void TestTreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyleOptionViewItem opt = option; + initStyleOption(&opt, index); + + bool italic = index.data(ItalicRole).toBool(); + if (italic) { + QFont font(option.font); + font.setItalic(true); + opt.font = font; + + // correct margin of items without a checkbox (except for root items) + QStyleOptionButton styleOpt; + styleOpt.initFrom(opt.widget); + const QSize sz; // no text, no icon - we just need the size of the check box + QSize cbSize = opt.widget->style()->sizeFromContents(QStyle::CT_CheckBox, &styleOpt, sz); + // the 6 results from hard coded margins of the checkbox itself (2x2) and the item (1x2) + opt.rect.setLeft(opt.rect.left() + cbSize.width() + 6); + + // HACK make sure the pixels that have been moved right are painted for selections + if (opt.state & QStyle::State_Selected) { + QPalette::ColorGroup cg = opt.state & QStyle::State_Enabled + ? QPalette::Normal : QPalette::Disabled; + if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active)) + cg = QPalette::Inactive; + painter->fillRect(option.rect, opt.palette.brush(cg, QPalette::Highlight)); + } + } + + QStyledItemDelegate::paint(painter, opt, index); +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testtreeitemdelegate.h b/plugins/autotest/testtreeitemdelegate.h new file mode 100644 index 00000000000..af31022b0bc --- /dev/null +++ b/plugins/autotest/testtreeitemdelegate.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTTREEITEMDELEGATE_H +#define TESTTREEITEMDELEGATE_H + +#include + +namespace Autotest { +namespace Internal { + +class TestTreeItemDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + TestTreeItemDelegate(QObject *parent = 0); + ~TestTreeItemDelegate(); + +public: + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; +}; + +} // namespace Internal +} // namespace Autotest + +#endif // TESTTREEITEMDELEGATE_H diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 93d9d160ef7..8425c27c1db 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -135,6 +135,8 @@ static QIcon testTreeIcon(TestTreeItem::Type type) QIcon(QLatin1String(":/images/class.png")), QIcon(QLatin1String(":/images/func.png")) }; + if (type >= 3) + return icons[2]; return icons[type]; } @@ -169,15 +171,46 @@ QVariant TestTreeModel::data(const QModelIndex &index, int role) const case Qt::DecorationRole: return testTreeIcon(item->type()); case Qt::CheckStateRole: - if (item->type() == TestTreeItem::ROOT) + switch (item->type()) { + case TestTreeItem::ROOT: + case TestTreeItem::TEST_DATAFUNCTION: + case TestTreeItem::TEST_SPECIALFUNCTION: return QVariant(); - return item->checked(); - case LinkRole: + case TestTreeItem::TEST_CLASS: + if (item->name().isEmpty()) + return QVariant(); + else + return item->checked(); + case TestTreeItem::TEST_FUNCTION: + if (TestTreeItem *parent = item->parent()) + return parent->name().isEmpty() ? QVariant() : item->checked(); + else + return item->checked(); + default: + return item->checked(); + } + case LinkRole: { QVariant itemLink; TextEditor::TextEditorWidget::Link link(item->filePath(), item->line(), item->column()); itemLink.setValue(link); return itemLink; } + case ItalicRole: + switch (item->type()) { + case TestTreeItem::TEST_DATAFUNCTION: + case TestTreeItem::TEST_SPECIALFUNCTION: + return true; + case TestTreeItem::TEST_CLASS: + return item->name().isEmpty(); + case TestTreeItem::TEST_FUNCTION: + if (TestTreeItem *parent = item->parent()) + return parent->name().isEmpty(); + else + return false; + default: + return false; + } + } // TODO ? return QVariant(); @@ -222,15 +255,18 @@ Qt::ItemFlags TestTreeModel::flags(const QModelIndex &index) const switch(item->type()) { case TestTreeItem::TEST_CLASS: if (item->name().isEmpty()) - return Qt::ItemIsSelectable | Qt::ItemIsTristate; + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsTristate | Qt::ItemIsUserCheckable; case TestTreeItem::TEST_FUNCTION: if (item->parent()->name().isEmpty()) - return Qt::ItemIsSelectable; + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable; case TestTreeItem::ROOT: - default: return Qt::ItemIsEnabled; + case TestTreeItem::TEST_DATAFUNCTION: + case TestTreeItem::TEST_SPECIALFUNCTION: + default: + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } } @@ -261,18 +297,38 @@ bool TestTreeModel::hasTests() const static void addProjectInformation(TestConfiguration *config, const QString &filePath) { + const ProjectExplorer::SessionManager *session = ProjectExplorer::SessionManager::instance(); + if (!session || !session->hasProjects()) + return; + + ProjectExplorer::Project *project = session->startupProject(); + if (!project) + return; + QString targetFile; QString targetName; QString workDir; QString proFile; + QString displayName; Utils::Environment env; - ProjectExplorer::Project *project = 0; + bool hasDesktopTarget = false; CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); - QList projParts = cppMM->projectPart(filePath); + QList projParts = cppMM->projectInfo(project).projectParts(); + if (!projParts.empty()) { - proFile = projParts.at(0)->projectFile; - project = projParts.at(0)->project; // necessary to grab this here? or should this be the current active startup project anyway? + foreach (const CppTools::ProjectPart::Ptr &part, projParts) { + foreach (const CppTools::ProjectFile currentFile, part->files) { + if (currentFile.path == filePath) { + proFile = part->projectFile; + displayName = part->displayName; + break; + } + } + if (!proFile.isEmpty()) // maybe better use a goto instead of the break above?? + break; + } } + if (project) { if (auto target = project->activeTarget()) { ProjectExplorer::BuildTargetInfoList appTargets = target->applicationTargets(); @@ -289,6 +345,7 @@ static void addProjectInformation(TestConfiguration *config, const QString &file if (ProjectExplorer::LocalApplicationRunConfiguration *localRunConfiguration = qobject_cast(rc)) { if (localRunConfiguration->executable() == targetFile) { + hasDesktopTarget = true; workDir = Utils::FileUtils::normalizePathName( localRunConfiguration->workingDirectory()); ProjectExplorer::EnvironmentAspect *envAsp @@ -300,12 +357,19 @@ static void addProjectInformation(TestConfiguration *config, const QString &file } } } - config->setTargetFile(targetFile); - config->setTargetName(targetName); - config->setWorkingDirectory(workDir); - config->setProFile(proFile); - config->setEnvironment(env); - config->setProject(project); + + if (hasDesktopTarget) { + config->setTargetFile(targetFile); + config->setTargetName(targetName); + config->setWorkingDirectory(workDir); + config->setProFile(proFile); + config->setEnvironment(env); + config->setProject(project); + config->setDisplayName(displayName); + } else { + config->setProFile(proFile); + config->setDisplayName(displayName); + } } QList TestTreeModel::getAllTestCases() const @@ -392,17 +456,18 @@ QList TestTreeModel::getSelectedTests() const QMap foundMains; - TestTreeItem *unnamed = unnamedQuickTests(); - for (int childRow = 0, ccount = unnamed->childCount(); childRow < ccount; ++ childRow) { - const TestTreeItem *grandChild = unnamed->child(childRow); - const QString mainFile = grandChild->mainFile(); - if (foundMains.contains(mainFile)) { - foundMains[mainFile]->setTestCaseCount(tc->testCaseCount() + 1); - } else { - TestConfiguration *tc = new TestConfiguration(QString(), QStringList()); - tc->setTestCaseCount(1); - addProjectInformation(tc, mainFile); - foundMains.insert(mainFile, tc); + if (TestTreeItem *unnamed = unnamedQuickTests()) { + for (int childRow = 0, ccount = unnamed->childCount(); childRow < ccount; ++ childRow) { + const TestTreeItem *grandChild = unnamed->child(childRow); + const QString mainFile = grandChild->mainFile(); + if (foundMains.contains(mainFile)) { + foundMains[mainFile]->setTestCaseCount(tc->testCaseCount() + 1); + } else { + TestConfiguration *tc = new TestConfiguration(QString(), QStringList()); + tc->setTestCaseCount(1); + addProjectInformation(tc, mainFile); + foundMains.insert(mainFile, tc); + } } } @@ -695,6 +760,8 @@ bool TestTreeSortFilterModel::lessThan(const QModelIndex &left, const QModelInde switch (m_sortMode) { case Alphabetically: + if (leftVal == rightVal) + return left.row() > right.row(); return leftVal > rightVal; case Naturally: { const TextEditor::TextEditorWidget::Link leftLink = @@ -717,13 +784,20 @@ bool TestTreeSortFilterModel::lessThan(const QModelIndex &left, const QModelInde bool TestTreeSortFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { - // TODO add filtering capabilities QModelIndex index = m_sourceModel->index(sourceRow, 0,sourceParent); if (!index.isValid()) return false; + const TestTreeItem *item = static_cast(index.internalPointer()); - return true; + switch (item->type()) { + case TestTreeItem::TEST_DATAFUNCTION: + return m_filterMode & ShowTestData; + case TestTreeItem::TEST_SPECIALFUNCTION: + return m_filterMode & ShowInitAndCleanup; + default: + return true; + } } } // namespace Internal diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 94cb874f8e5..5ae83f0df77 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -29,7 +29,8 @@ namespace { enum ItemRole { // AnnotationRole = Qt::UserRole + 1, - LinkRole = Qt::UserRole + 2 // can be removed if AnnotationRole comes back + LinkRole = Qt::UserRole + 2, // can be removed if AnnotationRole comes back + ItalicRole // used only inside the delegate }; } diff --git a/plugins/autotest/testtreeview.cpp b/plugins/autotest/testtreeview.cpp index 45376db3830..fdd3ee40966 100644 --- a/plugins/autotest/testtreeview.cpp +++ b/plugins/autotest/testtreeview.cpp @@ -20,6 +20,7 @@ #include "testcodeparser.h" #include "testrunner.h" #include "testtreeitem.h" +#include "testtreeitemdelegate.h" #include "testtreemodel.h" #include "testtreeview.h" @@ -53,6 +54,7 @@ TestTreeViewWidget::TestTreeViewWidget(QWidget *parent) : m_view = new TestTreeView(this); m_view->setModel(m_sortFilterModel); m_view->setSortingEnabled(true); + m_view->setItemDelegate(new TestTreeItemDelegate(this)); QVBoxLayout *layout = new QVBoxLayout; layout->setMargin(0); diff --git a/plugins/autotest/testvisitor.cpp b/plugins/autotest/testvisitor.cpp index 199f3236b22..b6706b5bf4c 100644 --- a/plugins/autotest/testvisitor.cpp +++ b/plugins/autotest/testvisitor.cpp @@ -44,7 +44,7 @@ TestVisitor::~TestVisitor() { } -static QList ignoredFunctions = QList() << QLatin1String("initTestCase") +static QList specialFunctions = QList() << QLatin1String("initTestCase") << QLatin1String("cleanupTestCase") << QLatin1String("init") << QLatin1String("cleanup"); @@ -66,14 +66,18 @@ bool TestVisitor::visit(CPlusPlus::Class *symbol) if (const auto func = type->asFunctionType()) { if (func->isSlot() && member->isPrivate()) { const QString name = o.prettyName(func->name()); - if (!ignoredFunctions.contains(name) && !name.endsWith(QLatin1String("_data"))) { - // TODO use definition of function instead of declaration! - TestCodeLocation location; - location.m_fileName = QLatin1String(member->fileName()); - location.m_line = member->line(); - location.m_column = member->column() - 1; - m_privSlots.insert(name, location); - } + // TODO use definition of function instead of declaration! + TestCodeLocationAndType locationAndType; + locationAndType.m_fileName = QLatin1String(member->fileName()); + locationAndType.m_line = member->line(); + locationAndType.m_column = member->column() - 1; + if (specialFunctions.contains(name)) + locationAndType.m_type = TestTreeItem::TEST_SPECIALFUNCTION; + else if (name.endsWith(QLatin1String("_data"))) + locationAndType.m_type = TestTreeItem::TEST_DATAFUNCTION; + else + locationAndType.m_type = TestTreeItem::TEST_FUNCTION; + m_privSlots.insert(name, locationAndType); } } } @@ -146,13 +150,14 @@ bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast) { const QStringRef name = ast->qualifiedTypeNameId->name; if (name != QLatin1String("TestCase")) - return false; + return true; // find nested TestCase items as well m_currentTestCaseName.clear(); const auto sourceLocation = ast->firstSourceLocation(); m_testCaseLocation.m_fileName = m_currentDoc->fileName(); m_testCaseLocation.m_line = sourceLocation.startLine; m_testCaseLocation.m_column = sourceLocation.startColumn - 1; + m_testCaseLocation.m_type = TestTreeItem::TEST_CLASS; return true; } @@ -173,12 +178,13 @@ bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast) const QStringRef name = ast->name; if (name.startsWith(QLatin1String("test_"))) { const auto sourceLocation = ast->firstSourceLocation(); - TestCodeLocation location; - location.m_fileName = m_currentDoc->fileName(); - location.m_line = sourceLocation.startLine; - location.m_column = sourceLocation.startColumn - 1; + TestCodeLocationAndType locationAndType; + locationAndType.m_fileName = m_currentDoc->fileName(); + locationAndType.m_line = sourceLocation.startLine; + locationAndType.m_column = sourceLocation.startColumn - 1; + locationAndType.m_type = TestTreeItem::TEST_FUNCTION; - m_testFunctions.insert(name.toString(), location); + m_testFunctions.insert(name.toString(), locationAndType); } return false; } diff --git a/plugins/autotest/testvisitor.h b/plugins/autotest/testvisitor.h index 92bfa009aea..bba9f0ebdae 100644 --- a/plugins/autotest/testvisitor.h +++ b/plugins/autotest/testvisitor.h @@ -19,6 +19,8 @@ #ifndef TESTVISITOR_H #define TESTVISITOR_H +#include "testtreeitem.h" + #include #include #include @@ -33,10 +35,11 @@ namespace Autotest { namespace Internal { -struct TestCodeLocation { +struct TestCodeLocationAndType { QString m_fileName; unsigned m_line; unsigned m_column; + TestTreeItem::Type m_type; }; class TestVisitor : public CPlusPlus::SymbolVisitor @@ -45,13 +48,13 @@ public: TestVisitor(const QString &fullQualifiedClassName); virtual ~TestVisitor(); - QMap privateSlots() const { return m_privSlots; } + QMap privateSlots() const { return m_privSlots; } bool visit(CPlusPlus::Class *symbol); private: QString m_className; - QMap m_privSlots; + QMap m_privSlots; }; class TestAstVisitor : public CPlusPlus::ASTVisitor @@ -85,14 +88,14 @@ public: bool visit(QmlJS::AST::StringLiteral *ast); QString testCaseName() const { return m_currentTestCaseName; } - TestCodeLocation testCaseLocation() const { return m_testCaseLocation; } - QMap testFunctions() const { return m_testFunctions; } + TestCodeLocationAndType testCaseLocation() const { return m_testCaseLocation; } + QMap testFunctions() const { return m_testFunctions; } private: QmlJS::Document::Ptr m_currentDoc; QString m_currentTestCaseName; - TestCodeLocation m_testCaseLocation; - QMap m_testFunctions; + TestCodeLocationAndType m_testCaseLocation; + QMap m_testFunctions; }; From 036c648650f646427be06e054371eb1971386fff Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 19 Nov 2014 08:52:40 +0100 Subject: [PATCH 019/200] Don't cancel test run if some test configurations are faulty Instead just remove these from the current test run and add a respective warning to the test results pane. Additionally made a the message of having no test cases at all a warning instead of a fatal. --- plugins/autotest/testresult.cpp | 2 +- plugins/autotest/testrunner.cpp | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp index e3b974113be..a784ec9b1a0 100644 --- a/plugins/autotest/testresult.cpp +++ b/plugins/autotest/testresult.cpp @@ -46,7 +46,7 @@ ResultType TestResult::resultFromString(const QString &resultString) return SKIP; if (resultString == QLatin1String("qdebug")) return MESSAGE_DEBUG; - if (resultString == QLatin1String("warn")) + if (resultString == QLatin1String("warn") || resultString == QLatin1String("qwarn")) return MESSAGE_WARN; if (resultString == QLatin1String("qfatal")) return MESSAGE_FATAL; diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 420360468bd..c7b582aab1e 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -343,9 +343,25 @@ void TestRunner::runTests() // clear old log and output pane TestResultsPane::instance()->clearContents(); + // handle faulty test configurations + QList toBeRemoved; + foreach (TestConfiguration *config, m_selectedTests) + if (!config->project()) { + toBeRemoved.append(config); + TestResultsPane::instance()->addTestResult( + TestResult(QString(), QString(), QString(), ResultType::MESSAGE_WARN, + tr("*** Project is null for '%1' - removing from Test Run ***\n" + "This might be the case for a faulty environment or similar." + ).arg(config->displayName()))); + } + foreach (TestConfiguration *config, toBeRemoved) { + m_selectedTests.removeOne(config); + delete config; + } + if (m_selectedTests.empty()) { TestResultsPane::instance()->addTestResult( - TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, + TestResult(QString(), QString(), QString(), ResultType::MESSAGE_WARN, tr("*** No tests selected - canceling Test Run ***"))); return; } From eb073616fbac1d5f1f4c537ecc36047ea43f8b0e Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 20 Nov 2014 13:57:41 +0100 Subject: [PATCH 020/200] Access test results list from multiple threads in a safe way This had lead to crashes when executing projects with some more tests or more test output. Now it's using a mutex to avoid concurrent access. --- plugins/autotest/testresultmodel.cpp | 16 ++++++++++++++++ plugins/autotest/testresultmodel.h | 2 ++ 2 files changed, 18 insertions(+) diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index 24a37c4886f..1fe13b57e89 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -36,6 +36,7 @@ TestResultModel::TestResultModel(QObject *parent) : TestResultModel::~TestResultModel() { + QWriteLocker lock(&m_rwLock); m_testResults.clear(); } @@ -53,6 +54,7 @@ QModelIndex TestResultModel::parent(const QModelIndex &) const int TestResultModel::rowCount(const QModelIndex &parent) const { + // do not use the QReadLocker here or this will produce a deadlock return parent.isValid() ? 0 : m_testResults.size(); } @@ -80,6 +82,7 @@ static QIcon testResultIcon(ResultType result) { QVariant TestResultModel::data(const QModelIndex &index, int role) const { + QReadLocker lock(&m_rwLock); if (!index.isValid() || index.row() >= m_testResults.count() || index.column() != 0) return QVariant(); if (role == Qt::DisplayRole) { @@ -106,8 +109,12 @@ QVariant TestResultModel::data(const QModelIndex &index, int role) const void TestResultModel::addTestResult(const TestResult &testResult) { + QReadLocker rLock(&m_rwLock); beginInsertRows(QModelIndex(), m_testResults.size(), m_testResults.size()); + rLock.unlock(); + QWriteLocker wLock(&m_rwLock); m_testResults.append(testResult); + wLock.unlock(); int count = m_testResultCount.value(testResult.result(), 0); m_testResultCount.insert(testResult.result(), ++count); endInsertRows(); @@ -116,10 +123,14 @@ void TestResultModel::addTestResult(const TestResult &testResult) void TestResultModel::clearTestResults() { + QReadLocker rLock(&m_rwLock); if (m_testResults.size() == 0) return; beginRemoveRows(QModelIndex(), 0, m_testResults.size() - 1); + rLock.unlock(); + QWriteLocker wLock(&m_rwLock); m_testResults.clear(); + wLock.unlock(); m_testResultCount.clear(); m_lastMaxWidthIndex = 0; m_maxWidthOfFileName = 0; @@ -132,12 +143,15 @@ TestResult TestResultModel::testResult(const QModelIndex &index) const { if (!index.isValid()) return TestResult(QString(), QString()); + QReadLocker lock(&m_rwLock); return m_testResults.at(index.row()); } int TestResultModel::maxWidthOfFileName(const QFont &font) { + QReadLocker lock(&m_rwLock); int count = m_testResults.size(); + lock.unlock(); if (count == 0) return 0; if (m_maxWidthOfFileName > 0 && font == m_measurementFont && m_lastMaxWidthIndex == count - 1) @@ -147,7 +161,9 @@ int TestResultModel::maxWidthOfFileName(const QFont &font) m_measurementFont = font; for (int i = m_lastMaxWidthIndex; i < count; ++i) { + lock.relock(); QString filename = m_testResults.at(i).fileName(); + lock.unlock(); const int pos = filename.lastIndexOf(QLatin1Char('/')); if (pos != -1) filename = filename.mid(pos +1); diff --git a/plugins/autotest/testresultmodel.h b/plugins/autotest/testresultmodel.h index 7618512fa26..1ef019a4567 100644 --- a/plugins/autotest/testresultmodel.h +++ b/plugins/autotest/testresultmodel.h @@ -24,6 +24,7 @@ #include #include #include +#include #include namespace Autotest { @@ -65,6 +66,7 @@ private: int m_lastMaxWidthIndex; QFont m_measurementFont; QSet m_availableResultTypes; + mutable QReadWriteLock m_rwLock; }; class TestResultFilterModel : public QSortFilterProxyModel From 0fc6d113d1befa33485adee3de77ad8b2ec0e985 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 25 Nov 2014 09:32:13 +0100 Subject: [PATCH 021/200] Update test tree when configuration changes This takes especially configurations in account when subprojects are enabled/disabled conditionally. --- plugins/autotest/autotest_dependencies.pri | 1 + plugins/autotest/testcodeparser.cpp | 185 +++++++++++++++++++-- plugins/autotest/testcodeparser.h | 5 +- plugins/autotest/testinfo.h | 5 +- 4 files changed, 177 insertions(+), 19 deletions(-) diff --git a/plugins/autotest/autotest_dependencies.pri b/plugins/autotest/autotest_dependencies.pri index 6546683f456..a21b5fce963 100644 --- a/plugins/autotest/autotest_dependencies.pri +++ b/plugins/autotest/autotest_dependencies.pri @@ -5,6 +5,7 @@ QTC_PLUGIN_DEPENDS += \ projectexplorer \ cpptools \ qmljstools \ + qmakeprojectmanager \ licensechecker QTC_LIB_DEPENDS += \ diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 240bb418d55..a0ba1534ce3 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -31,6 +31,7 @@ #include +#include #include #include #include @@ -61,6 +62,13 @@ void TestCodeParser::updateTestTree() m_model->removeAllQuickTests(); const ProjectExplorer::SessionManager *session = ProjectExplorer::SessionManager::instance(); if (!session || !session->hasProjects()) { + if (m_currentProject) { + if (QmakeProjectManager::QmakeProject *qmproj + = qobject_cast(m_currentProject)) { + disconnect(qmproj, &QmakeProjectManager::QmakeProject::proFilesEvaluated, + this, &TestCodeParser::onProFileEvaluated); + } + } m_currentProject = 0; return; } @@ -68,6 +76,13 @@ void TestCodeParser::updateTestTree() m_currentProject = session->startupProject(); if (!m_currentProject) return; + else { + if (QmakeProjectManager::QmakeProject *qmproj + = qobject_cast(m_currentProject)) { + connect(qmproj, &QmakeProjectManager::QmakeProject::proFilesEvaluated, + this, &TestCodeParser::onProFileEvaluated); + } + } scanForTests(); } @@ -241,6 +256,13 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) const QString file = doc->fileName(); const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + QList projParts = cppMM->projectPart(file); + if (projParts.size()) + if (!projParts.at(0)->selectedForBuilding) { + removeTestsIfNecessary(file); + return; + } + if (includesQtQuickTest(doc, cppMM)) { handleQtQuickTest(doc); return; @@ -299,6 +321,11 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) // TODO refactoring? // update model and internal map + QString proFile; + QList ppList = cppMM->projectPart(file); + if (ppList.size()) + proFile = ppList.at(0)->projectFile; + TestInfo info; int count; if (m_cppDocMap.contains(file)) { @@ -308,9 +335,9 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) TestTreeItem *currentItem = autoTestRootItem->child(i); if (currentItem->filePath() == file) { m_model->modifyAutoTestSubtree(i, ttItem); - m_cppDocMap.insert(file, TestInfo(tc, privSlots.keys(), - doc->revision(), - doc->editorRevision())); + TestInfo ti(tc, privSlots.keys(), doc->revision(), doc->editorRevision()); + ti.setProfile(proFile); + m_cppDocMap.insert(file, ti); break; } } @@ -324,6 +351,7 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) TestInfo ti(tc, privSlots.keys(), doc->revision(), doc->editorRevision()); ti.setReferencingFile(file); + ti.setProfile(proFile); m_cppDocMap.insert(declFileName, ti); break; } @@ -332,11 +360,13 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) delete ttItem; } else { m_model->addAutoTest(ttItem); - m_cppDocMap.insert(file, TestInfo(tc, privSlots.keys(), doc->revision(), - doc->editorRevision())); + TestInfo ti(tc, privSlots.keys(), doc->revision(), doc->editorRevision()); + ti.setProfile(proFile); + m_cppDocMap.insert(file, ti); if (declFileName != file) { TestInfo ti(tc, privSlots.keys(), doc->revision(), doc->editorRevision()); ti.setReferencingFile(file); + ti.setProfile(proFile); m_cppDocMap.insert(declFileName, ti); } } @@ -466,6 +496,10 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr doc) const QString fileName(tcLocationAndType.m_fileName); const QmlJS::Document::Ptr qmlDoc = QmlJSTools::Internal::ModelManager::instance()->snapshot().document(fileName); + QString proFile; + QList ppList = cppMM->projectPart(doc->fileName()); + if (ppList.size()) + proFile = ppList.at(0)->projectFile; if (m_quickDocMap.contains(fileName)) { for (int i = 0; i < quickTestRootItem->childCount(); ++i) { @@ -473,6 +507,7 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr doc) m_model->modifyQuickTestSubtree(i, ttItem); TestInfo ti(tcName, testFunctions.keys(), 0, qmlDoc->editorRevision()); ti.setReferencingFile(doc->fileName()); + ti.setProfile(proFile); m_quickDocMap.insert(fileName, ti); break; } @@ -499,6 +534,7 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr doc) m_model->addQuickTest(ttItem); TestInfo ti(tcName, testFunctions.keys(), 0, qmlDoc->editorRevision()); ti.setReferencingFile(doc->fileName()); + ti.setProfile(proFile); m_quickDocMap.insert(tcLocationAndType.m_fileName, ti); } } @@ -557,21 +593,19 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &doc) void TestCodeParser::removeFiles(const QStringList &files) { - foreach (const QString &file, files) { - if (m_cppDocMap.contains(file)) { - m_cppDocMap.remove(file); - m_model->removeAutoTestSubtreeByFilePath(file); - } - if (m_quickDocMap.contains(file)) { - m_quickDocMap.remove(file); - m_model->removeQuickTestSubtreeByFilePath(file); - } - } + foreach (const QString &file, files) + removeTestsIfNecessary(file); } -void TestCodeParser::scanForTests() +void TestCodeParser::scanForTests(const QStringList &fileList) { - const QStringList list = m_currentProject->files(ProjectExplorer::Project::AllFiles); + QStringList list; + if (fileList.isEmpty()) { + list = m_currentProject->files(ProjectExplorer::Project::AllFiles); + } else { + list << fileList; + } + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); CPlusPlus::Snapshot snapshot = cppMM->snapshot(); @@ -589,5 +623,122 @@ void TestCodeParser::clearMaps() m_quickDocMap.clear(); } +void TestCodeParser::removeTestsIfNecessary(const QString &fileName) +{ + // check if this file was listed before and remove if necessary (switched config,...) + if (m_cppDocMap.contains(fileName)) { + m_cppDocMap.remove(fileName); + m_model->removeAutoTestSubtreeByFilePath(fileName); + } else { // handle Qt Quick Tests + QList toBeRemoved; + foreach (const QString &file, m_quickDocMap.keys()) { + if (file == fileName) { + toBeRemoved.append(file); + continue; + } + const TestInfo info = m_quickDocMap.value(file); + if (info.referencingFile() == fileName) + toBeRemoved.append(file); + } + foreach (const QString &file, toBeRemoved) { + m_quickDocMap.remove(file); + m_model->removeQuickTestSubtreeByFilePath(file); + } + // unnamed Quick Tests must be handled separately + QSet filePaths; + QList functionNames; + if (TestTreeItem *unnamedQT = m_model->unnamedQuickTests()) { + for (int i = 0; i < unnamedQT->childCount(); ++i) { + const TestTreeItem *child = unnamedQT->child(i); + if (child->mainFile() == fileName) { + filePaths.insert(child->filePath()); + functionNames.append(child->name()); + } + } + foreach (const QString &file, filePaths) + m_model->removeUnnamedQuickTests(file); + // update info map + TestInfo unnamedInfo = m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)]; + QStringList functions = unnamedInfo.testFunctions(); + foreach (const QString &func, functionNames) + functions.removeOne(func); + unnamedInfo.setTestFunctions(functions); + if (functions.size() == 0) + m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); + else + m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), unnamedInfo); + } + } +} + + +void TestCodeParser::removeTestsIfNecessaryByProFile(const QString &proFile) +{ + QList fl; + foreach (const QString &fn, m_cppDocMap.keys()) { + if (m_cppDocMap[fn].proFile() == proFile) + fl.append(fn); + } + foreach (const QString &fn, fl) { + m_cppDocMap.remove(fn); + m_model->removeAutoTestSubtreeByFilePath(fn); + } + fl.clear(); + foreach (const QString &fn, m_quickDocMap.keys()) { + if (m_quickDocMap[fn].proFile() == proFile) + fl.append(fn); + } + foreach (const QString &fn, fl) { + m_quickDocMap.remove(fn); + m_model->removeQuickTestSubtreeByFilePath(fn); + } + // handle unnamed Quick Tests + fl.clear(); // will now be re-used as function names storage + QSet filePaths; + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + if (TestTreeItem *unnamedQT = m_model->unnamedQuickTests()) { + for (int i = 0; i < unnamedQT->childCount(); ++i) { + const TestTreeItem *child = unnamedQT->child(i); + QList ppList = cppMM->projectPart(child->mainFile()); + if (ppList.size() && ppList.at(0)->projectFile == proFile) { + filePaths.insert(child->filePath()); + fl.append(child->name()); + } + } + } + foreach (const QString &fp, filePaths) { + m_model->removeUnnamedQuickTests(fp); + } + // update info map + TestInfo unnamedInfo = m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)]; + QStringList functions = unnamedInfo.testFunctions(); + foreach (const QString &func, fl) + functions.removeOne(func); + unnamedInfo.setTestFunctions(functions); + if (functions.size() == 0) + m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); + else + m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), unnamedInfo); +} + +void TestCodeParser::onProFileEvaluated() +{ + if (!m_currentProject) + return; + + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + const QList pp = cppMM->projectInfo(m_currentProject).projectParts(); + foreach (const CppTools::ProjectPart::Ptr &p, pp) { + if (!p->selectedForBuilding) + removeTestsIfNecessaryByProFile(p->projectFile); + else { + QStringList files; + foreach (auto projectFile, p->files) + files.append(projectFile.path); + scanForTests(files); + } + } +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 5b422ba0e6e..da89eb51d7f 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -53,10 +53,13 @@ public slots: void onCppDocumentUpdated(const CPlusPlus::Document::Ptr &doc); void onQmlDocumentUpdated(const QmlJS::Document::Ptr &doc); void removeFiles(const QStringList &files); + void onProFileEvaluated(); private: - void scanForTests(); + void scanForTests(const QStringList &fileList = QStringList()); void clearMaps(); + void removeTestsIfNecessary(const QString &fileName); + void removeTestsIfNecessaryByProFile(const QString &proFile); TestTreeModel *m_model; QMap m_cppDocMap; diff --git a/plugins/autotest/testinfo.h b/plugins/autotest/testinfo.h index c03236416da..b974824f9e0 100644 --- a/plugins/autotest/testinfo.h +++ b/plugins/autotest/testinfo.h @@ -41,7 +41,9 @@ public: unsigned editorRevision() const { return m_editorRevision; } void setEditorRevision(unsigned editorRevision) { m_editorRevision = editorRevision; } const QString referencingFile() const { return m_referencingFile; } - void setReferencingFile(const QString &refFile) {m_referencingFile = refFile; } + void setReferencingFile(const QString &refFile) { m_referencingFile = refFile; } + const QString proFile() const { return m_proFile; } + void setProfile(const QString &proFile) { m_proFile = proFile; } private: QString m_className; @@ -49,6 +51,7 @@ private: unsigned m_revision; unsigned m_editorRevision; QString m_referencingFile; + QString m_proFile; }; } // namespace Internal From d2784769567a96221ac036e90b1f3f207257cf27 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 1 Dec 2014 11:42:28 +0100 Subject: [PATCH 022/200] Support blacklisted test cases --- plugins/autotest/autotest.qrc | 2 ++ plugins/autotest/images/blacklisted_fail.png | Bin 0 -> 520 bytes plugins/autotest/images/blacklisted_pass.png | Bin 0 -> 519 bytes plugins/autotest/testresult.cpp | 16 ++++++++++++++++ plugins/autotest/testresult.h | 2 ++ plugins/autotest/testresultdelegate.cpp | 4 ++++ plugins/autotest/testresultmodel.cpp | 9 +++++++-- plugins/autotest/testresultspane.cpp | 6 ++++++ 8 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 plugins/autotest/images/blacklisted_fail.png create mode 100644 plugins/autotest/images/blacklisted_pass.png diff --git a/plugins/autotest/autotest.qrc b/plugins/autotest/autotest.qrc index fe59718a584..e76830ba046 100644 --- a/plugins/autotest/autotest.qrc +++ b/plugins/autotest/autotest.qrc @@ -14,6 +14,8 @@ images/warn.png images/xfail.png images/xpass.png + images/blacklisted_fail.png + images/blacklisted_pass.png images/run.png images/runselected.png images/stop.png diff --git a/plugins/autotest/images/blacklisted_fail.png b/plugins/autotest/images/blacklisted_fail.png new file mode 100644 index 0000000000000000000000000000000000000000..695e1f9246856f97b9fd7f952f2bce22a5407761 GIT binary patch literal 520 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7&wIK!hFJ72y?oYNBthW# z$Mc(4?p~LFAxQ7XB)KKsimEOFF71A@Jqm}aFW3uwu`l_YArQMNx_t!)lcUQ^p%f3X zD$bkElb&viTATUqa^n1yvw5}#(<{^Vo&S^ejMLEVfAOq;Wi0|mi+kiB-x2gH-_RSL zy6oMtA7315l3CrIC8Sc4W_a6bENU=g+4K0IhZ)x)Cpp*kw|@BG*<(C2b?v=(Yg6nuH1-{JEi4K;@ia$QXT<~SO+6+|WvgF4lGcjwH&U{i zKE0LYZ;yUy#ah7+Rn6U^Q!d|#y5ws5RcXnoeM!8l&zLi%6=vJAnyWuATctLg!Tz$w z^&7f|+u1t|?YI?fZasOG<#o?<(yiB3-+$T_Jg@E1&x}|i;56TA>wf0;%X%iKZm#sM z*?g+?tAzHY*VS!~Hf}se{F2N!PQT&4_JFO3RPmwxb;%qLrOrJ_sj84OHazy6J?Z~< c>;G(DvUkjAcbp>3z`(%Z>FVdQ&MBb@0Iag@R{#J2 literal 0 HcmV?d00001 diff --git a/plugins/autotest/images/blacklisted_pass.png b/plugins/autotest/images/blacklisted_pass.png new file mode 100644 index 0000000000000000000000000000000000000000..bac3ffb1342bbfa8d291fcfc41f7fc2ce95427d8 GIT binary patch literal 519 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7&w08yhFJ72z3l5P5+HKy ztPvLH7igJvVexV6*iEx8G<{3C)W8#U z_wow;IsDfjm7MW>8gxanG$t%}R>c~Vy{p!q3V1$Y;yJ;)Z|}}2zUJHiO|V5E@AR&x z9;;+rMYCS4e{FupX3gS7htmo#JH2H}zr)}BFjA&pcsC2P((g?Xr)m`Q>$2~?xwa-o z(VbCJQkU&idBI7(vJI{GZyeB13rp)cYIt?wtuMb!R!6um<$lV>I@@zgoY1L-yIhR7 zTZP}c#y0Kp?OjPb52k15MI7bIx-6Hlc?-AV#ituvT!Wvoz5iH{|7u-@^~Dg?=G--j zo(Ib(SF;%&yRO(Ge(laj<<4@UB3Z4;2lI08J^rCvx8RMCGsoQ-M?AkSl`hbE7_N5N z{>0Bm%U>5-K3n>-x-+<!5W$hxpz_7s0>KU5XTmJt&CU7V==HO8lyVg#L$3GhH e9j<%6-$7v0(SyCorx_R+7(8A5T-G@yGywpiwe&{- literal 0 HcmV?d00001 diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp index a784ec9b1a0..0373b72010a 100644 --- a/plugins/autotest/testresult.cpp +++ b/plugins/autotest/testresult.cpp @@ -50,6 +50,10 @@ ResultType TestResult::resultFromString(const QString &resultString) return MESSAGE_WARN; if (resultString == QLatin1String("qfatal")) return MESSAGE_FATAL; + if (resultString == QLatin1String("bpass")) + return BLACKLISTED_PASS; + if (resultString == QLatin1String("bfail")) + return BLACKLISTED_FAIL; qDebug(" unexpected testresult..."); qDebug(resultString.toLatin1()); return UNKNOWN; @@ -68,6 +72,10 @@ ResultType TestResult::toResultType(int rt) return UNEXPECTED_PASS; case SKIP: return SKIP; + case BLACKLISTED_PASS: + return BLACKLISTED_PASS; + case BLACKLISTED_FAIL: + return BLACKLISTED_FAIL; case MESSAGE_DEBUG: return MESSAGE_DEBUG; case MESSAGE_WARN: @@ -102,6 +110,10 @@ QString TestResult::resultToString(const ResultType type) return QLatin1String("FATAL"); case MESSAGE_INTERNAL: return QString(); + case BLACKLISTED_PASS: + return QLatin1String("BPASS"); + case BLACKLISTED_FAIL: + return QLatin1String("BFAIL"); default: return QLatin1String("UNKNOWN"); } @@ -120,6 +132,10 @@ QColor TestResult::colorForType(const ResultType type) return QColor("#ff0000"); case SKIP: return QColor("#787878"); + case BLACKLISTED_PASS: + return QColor(0, 0, 0); + case BLACKLISTED_FAIL: + return QColor(0, 0, 0); case MESSAGE_DEBUG: return QColor("#329696"); case MESSAGE_WARN: diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index aa0d01e4e7c..f1f246ef49c 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -31,6 +31,8 @@ enum ResultType { EXPECTED_FAIL, UNEXPECTED_PASS, SKIP, + BLACKLISTED_PASS, + BLACKLISTED_FAIL, MESSAGE_DEBUG, MESSAGE_WARN, MESSAGE_FATAL, diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp index 4231278276a..b3b210f11d8 100644 --- a/plugins/autotest/testresultdelegate.cpp +++ b/plugins/autotest/testresultdelegate.cpp @@ -91,6 +91,8 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op case ResultType::FAIL: case ResultType::EXPECTED_FAIL: case ResultType::UNEXPECTED_PASS: + case ResultType::BLACKLISTED_FAIL: + case ResultType::BLACKLISTED_PASS: output = testResult.className() + QLatin1String("::") + testResult.testCase(); if (!testResult.dataTag().isEmpty()) output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); @@ -192,6 +194,8 @@ QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo case ResultType::FAIL: case ResultType::EXPECTED_FAIL: case ResultType::UNEXPECTED_PASS: + case ResultType::BLACKLISTED_FAIL: + case ResultType::BLACKLISTED_PASS: output = testResult.className() + QLatin1String("::") + testResult.testCase(); if (!testResult.dataTag().isEmpty()) output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index 1fe13b57e89..ab303364c40 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -64,12 +64,14 @@ int TestResultModel::columnCount(const QModelIndex &parent) const } static QIcon testResultIcon(ResultType result) { - static QIcon icons[8] = { + static QIcon icons[10] = { QIcon(QLatin1String(":/images/pass.png")), QIcon(QLatin1String(":/images/fail.png")), QIcon(QLatin1String(":/images/xfail.png")), QIcon(QLatin1String(":/images/xpass.png")), QIcon(QLatin1String(":/images/skip.png")), + QIcon(QLatin1String(":/images/blacklisted_pass.png")), + QIcon(QLatin1String(":/images/blacklisted_fail.png")), QIcon(QLatin1String(":/images/debug.png")), QIcon(QLatin1String(":/images/warn.png")), QIcon(QLatin1String(":/images/fatal.png")), @@ -93,6 +95,8 @@ QVariant TestResultModel::data(const QModelIndex &index, int role) const case ResultType::EXPECTED_FAIL: case ResultType::UNEXPECTED_PASS: case ResultType::SKIP: + case ResultType::BLACKLISTED_PASS: + case ResultType::BLACKLISTED_FAIL: return QString::fromLatin1("%1::%2 (%3) - %4").arg(tr.className(), tr.testCase(), tr.dataTag(), tr.fileName()); default: @@ -204,7 +208,8 @@ void TestResultFilterModel::enableAllResultTypes() m_enabled << ResultType::PASS << ResultType::FAIL << ResultType::EXPECTED_FAIL << ResultType::UNEXPECTED_PASS << ResultType::SKIP << ResultType::MESSAGE_DEBUG << ResultType::MESSAGE_WARN << ResultType::MESSAGE_INTERNAL - << ResultType::MESSAGE_FATAL << ResultType::UNKNOWN; + << ResultType::MESSAGE_FATAL << ResultType::UNKNOWN << ResultType::BLACKLISTED_PASS + << ResultType::BLACKLISTED_FAIL; invalidateFilter(); } diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 39441d90876..45c8d4085b2 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -313,6 +313,12 @@ void TestResultsPane::updateSummaryLabel() if (count) labelText.append(QString::fromLatin1(", %1 %2") .arg(QString::number(count), tr("fatals"))); + count = m_model->resultTypeCount(ResultType::BLACKLISTED_FAIL) + + m_model->resultTypeCount(ResultType::BLACKLISTED_PASS); + if (count) + labelText.append(QString::fromLatin1(", %1 %2") + .arg(QString::number(count), tr("blacklisted"))); + labelText.append(QLatin1String(".

")); m_summaryLabel->setText(labelText); } From 32a6849fae4cfa35a8c5f395701cdbb15c31ef03 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 1 Dec 2014 16:12:05 +0100 Subject: [PATCH 023/200] Add support for minimal benchmarks --- plugins/autotest/autotest.qrc | 1 + plugins/autotest/images/benchmark.png | Bin 0 -> 374 bytes plugins/autotest/testresult.cpp | 4 +++ plugins/autotest/testresult.h | 1 + plugins/autotest/testresultdelegate.cpp | 38 +++++++++++++++++++----- plugins/autotest/testresultmodel.cpp | 6 ++-- plugins/autotest/testresultspane.cpp | 1 + plugins/autotest/testrunner.cpp | 37 +++++++++++++++++++++++ 8 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 plugins/autotest/images/benchmark.png diff --git a/plugins/autotest/autotest.qrc b/plugins/autotest/autotest.qrc index e76830ba046..7b98beaab96 100644 --- a/plugins/autotest/autotest.qrc +++ b/plugins/autotest/autotest.qrc @@ -16,6 +16,7 @@ images/xpass.png images/blacklisted_fail.png images/blacklisted_pass.png + images/benchmark.png images/run.png images/runselected.png images/stop.png diff --git a/plugins/autotest/images/benchmark.png b/plugins/autotest/images/benchmark.png new file mode 100644 index 0000000000000000000000000000000000000000..c9d3c5b2b50546b0261e7889245436fbc6e0882d GIT binary patch literal 374 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4rT@h1`S>QUwy?Xun^&2;CJh*%J z+0&<=K7IQ7_3QWV-+zAp{_EGTKY#xG{rmUdzkmP#|DWQqxr~8qqe&~Mxc=n2~Zk%GP6|}o_A`;WyMU~m=M+*ycO84DcUaWB;setPen(tmp); } + const QString desc = testResult.description(); QString output; switch (type) { case ResultType::PASS: @@ -96,13 +97,23 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op output = testResult.className() + QLatin1String("::") + testResult.testCase(); if (!testResult.dataTag().isEmpty()) output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); - if (selected && !testResult.description().isEmpty()) { - output.append(QLatin1Char('\n')); - output.append(testResult.description()); + if (selected && !desc.isEmpty()) { + output.append(QLatin1Char('\n')).append(desc); + } + break; + case ResultType::BENCHMARK: + output = testResult.className() + QLatin1String("::") + testResult.testCase(); + if (!testResult.dataTag().isEmpty()) + output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); + if (!desc.isEmpty()) { + int breakPos = desc.indexOf(QLatin1Char('(')); + output.append(QLatin1String(" - ")).append(desc.left(breakPos)); + if (selected) + output.append(QLatin1Char('\n')).append(desc.mid(breakPos)); } break; default: - output = testResult.description(); + output = desc; if (!selected) output = output.split(QLatin1Char('\n')).first(); } @@ -188,6 +199,7 @@ QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo if (selected) { TestResult testResult = resultModel->testResult(resultFilterModel->mapToSource(index)); + QString desc = testResult.description(); QString output; switch (testResult.result()) { case ResultType::PASS: @@ -199,13 +211,23 @@ QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo output = testResult.className() + QLatin1String("::") + testResult.testCase(); if (!testResult.dataTag().isEmpty()) output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); - if (!testResult.description().isEmpty()) { - output.append(QLatin1Char('\n')); - output.append(testResult.description()); + if (!desc.isEmpty()) { + output.append(QLatin1Char('\n')).append(desc); + } + break; + case ResultType::BENCHMARK: + output = testResult.className() + QLatin1String("::") + testResult.testCase(); + if (!testResult.dataTag().isEmpty()) + output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); + if (!desc.isEmpty()) { + int breakPos = desc.indexOf(QLatin1Char('(')); + output.append(QLatin1String(" - ")).append(desc.left(breakPos)); + if (selected) + output.append(QLatin1Char('\n')).append(desc.mid(breakPos)); } break; default: - output = testResult.description(); + output = desc; } output.replace(QLatin1Char('\n'), QChar::LineSeparator); diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index ab303364c40..8a5e8aca64b 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -64,7 +64,7 @@ int TestResultModel::columnCount(const QModelIndex &parent) const } static QIcon testResultIcon(ResultType result) { - static QIcon icons[10] = { + static QIcon icons[11] = { QIcon(QLatin1String(":/images/pass.png")), QIcon(QLatin1String(":/images/fail.png")), QIcon(QLatin1String(":/images/xfail.png")), @@ -72,6 +72,7 @@ static QIcon testResultIcon(ResultType result) { QIcon(QLatin1String(":/images/skip.png")), QIcon(QLatin1String(":/images/blacklisted_pass.png")), QIcon(QLatin1String(":/images/blacklisted_fail.png")), + QIcon(QLatin1String(":/images/benchmark.png")), QIcon(QLatin1String(":/images/debug.png")), QIcon(QLatin1String(":/images/warn.png")), QIcon(QLatin1String(":/images/fatal.png")), @@ -97,6 +98,7 @@ QVariant TestResultModel::data(const QModelIndex &index, int role) const case ResultType::SKIP: case ResultType::BLACKLISTED_PASS: case ResultType::BLACKLISTED_FAIL: + case ResultType::BENCHMARK: return QString::fromLatin1("%1::%2 (%3) - %4").arg(tr.className(), tr.testCase(), tr.dataTag(), tr.fileName()); default: @@ -209,7 +211,7 @@ void TestResultFilterModel::enableAllResultTypes() << ResultType::UNEXPECTED_PASS << ResultType::SKIP << ResultType::MESSAGE_DEBUG << ResultType::MESSAGE_WARN << ResultType::MESSAGE_INTERNAL << ResultType::MESSAGE_FATAL << ResultType::UNKNOWN << ResultType::BLACKLISTED_PASS - << ResultType::BLACKLISTED_FAIL; + << ResultType::BLACKLISTED_FAIL << ResultType::BENCHMARK; invalidateFilter(); } diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 45c8d4085b2..998e80f57fe 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -277,6 +277,7 @@ void TestResultsPane::initializeFilterMenu() textAndType.insert(ResultType::EXPECTED_FAIL, tr("Expected Fail")); textAndType.insert(ResultType::UNEXPECTED_PASS, tr("Unexpected Pass")); textAndType.insert(ResultType::SKIP, tr("Skip")); + textAndType.insert(ResultType::BENCHMARK, tr("Benchmarks")); textAndType.insert(ResultType::MESSAGE_DEBUG, tr("Debug Messages")); textAndType.insert(ResultType::MESSAGE_WARN, tr("Warning Messages")); textAndType.insert(ResultType::MESSAGE_INTERNAL, tr("Internal Messages")); diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index c7b582aab1e..b3abaf71948 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -112,6 +112,37 @@ static bool xmlExtractTypeFileLine(const QString &code, const QString &tagStart, return false; } +static bool xmlExtractBenchmarkInformation(const QString &code, const QString &tagStart, + QString &description) +{ + if (code.startsWith(tagStart)) { + int start = code.indexOf(QLatin1String(" metric=\"")) + 9; + const QString metric = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start); + start = code.indexOf(QLatin1String(" value=\"")) + 8; + const double value = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start).toDouble(); + start = code.indexOf(QLatin1String(" iterations=\"")) + 13; + const int iterations = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start).toInt(); + QString metricsTxt; + if (metric == QLatin1String("WalltimeMilliseconds")) // default + metricsTxt = QLatin1String("msecs"); + else if (metric == QLatin1String("CPUTicks")) // -tickcounter + metricsTxt = QLatin1String("CPU ticks"); + else if (metric == QLatin1String("Events")) // -eventcounter + metricsTxt = QLatin1String("events"); + else if (metric == QLatin1String("InstructionReads")) // -callgrind + metricsTxt = QLatin1String("instruction reads"); + else if (metric == QLatin1String("CPUCycles")) // -perf + metricsTxt = QLatin1String("CPU cycles"); + description = QObject::tr("%1 %2 per iteration (total: %3, iterations: %4)") + .arg(QString::number(value, 'f', 6)) + .arg(metricsTxt) + .arg(QString::number(value * (double)iterations, 'g', 3)) + .arg(iterations); + return true; + } + return false; +} + /****************** XML line parser helper end ******************/ void processOutput() @@ -129,6 +160,7 @@ void processOutput() static bool readingDescription = false; static QString qtVersion; static QString qtestVersion; + static QString bmDescription; while (m_runner->canReadLine()) { // TODO Qt5 uses UTF-8 - while Qt4 uses ISO-8859-1 - could this be a problem? @@ -172,6 +204,11 @@ void processOutput() } continue; } + if (xmlExtractBenchmarkInformation(line, QLatin1String("addTestResult(testResult); + continue; + } if (line == QLatin1String("") || line == QLatin1String("")) { TestResult testResult(className, testCase, dataTag, result, description); if (!file.isEmpty()) From edfd394bf54bc78f2a85104da2f49484a61d1134 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 5 Dec 2014 08:39:24 +0100 Subject: [PATCH 024/200] Fix issue when buildQueueFinished signal is emitted too fast Change-Id: I56ba8f9d0d4abe7627f9dd0d980774dda814d456 Reviewed-by: Christian Stenger --- plugins/autotest/testrunner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index b3abaf71948..2c0b035a1c7 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -451,9 +451,9 @@ void TestRunner::buildProject(ProjectExplorer::Project *project) ProjectExplorer::BuildManager *mgr = static_cast( ProjectExplorer::BuildManager::instance()); ProjectExplorer::ProjectExplorerPlugin *pep = ProjectExplorer::ProjectExplorerPlugin::instance(); - pep->buildProject(project); connect(mgr, &ProjectExplorer::BuildManager::buildQueueFinished, this, &TestRunner::buildFinished); + pep->buildProject(project); } void TestRunner::buildFinished(bool success) From e71a2c44fc64b3e3ced132731bf57fc6809516e1 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 4 Dec 2014 14:05:19 +0100 Subject: [PATCH 025/200] Provide test settings and make use of them Change-Id: Ia6fef10bc577f9722b6c063c2df4d1651a8be50d Reviewed-by: Christian Stenger --- plugins/autotest/autotest.pro | 11 +- plugins/autotest/autotest.qrc | 1 + plugins/autotest/autotestconstants.h | 13 +- plugins/autotest/autotestplugin.cpp | 15 ++ plugins/autotest/autotestplugin.h | 9 + plugins/autotest/images/autotest.png | Bin 0 -> 683 bytes plugins/autotest/testresultspane.cpp | 9 +- plugins/autotest/testrunner.cpp | 63 ++++++- plugins/autotest/testsettings.cpp | 97 ++++++++++ plugins/autotest/testsettings.h | 58 ++++++ plugins/autotest/testsettingspage.cpp | 119 ++++++++++++ plugins/autotest/testsettingspage.h | 66 +++++++ plugins/autotest/testsettingspage.ui | 258 ++++++++++++++++++++++++++ 13 files changed, 706 insertions(+), 13 deletions(-) create mode 100644 plugins/autotest/images/autotest.png create mode 100644 plugins/autotest/testsettings.cpp create mode 100644 plugins/autotest/testsettings.h create mode 100644 plugins/autotest/testsettingspage.cpp create mode 100644 plugins/autotest/testsettingspage.h create mode 100644 plugins/autotest/testsettingspage.ui diff --git a/plugins/autotest/autotest.pro b/plugins/autotest/autotest.pro index 6d2423bdd74..507d9303003 100644 --- a/plugins/autotest/autotest.pro +++ b/plugins/autotest/autotest.pro @@ -22,7 +22,9 @@ SOURCES += \ testresultspane.cpp \ testresultmodel.cpp \ testresultdelegate.cpp \ - testtreeitemdelegate.cpp + testtreeitemdelegate.cpp \ + testsettings.cpp \ + testsettingspage.cpp HEADERS += \ testtreeview.h \ @@ -40,8 +42,13 @@ HEADERS += \ testresultspane.h \ testresultmodel.h \ testresultdelegate.h \ - testtreeitemdelegate.h + testtreeitemdelegate.h \ + testsettings.h \ + testsettingspage.h RESOURCES += \ autotest.qrc +FORMS += \ + testsettingspage.ui + diff --git a/plugins/autotest/autotest.qrc b/plugins/autotest/autotest.qrc index 7b98beaab96..2770aff5fe2 100644 --- a/plugins/autotest/autotest.qrc +++ b/plugins/autotest/autotest.qrc @@ -1,5 +1,6 @@ + images/autotest.png images/class.png images/func.png images/expand.png diff --git a/plugins/autotest/autotestconstants.h b/plugins/autotest/autotestconstants.h index a4f6bdc7d9f..fc254e42283 100644 --- a/plugins/autotest/autotestconstants.h +++ b/plugins/autotest/autotestconstants.h @@ -24,12 +24,13 @@ namespace Autotest { namespace Constants { -const char ACTION_ID[] = "AutoTest.Action"; -const char MENU_ID[] = "AutoTest.Menu"; -const char AUTOTEST_ID[] = "AutoTest.ATP"; -const char AUTOTEST_CONTEXT[] = "Auto Tests"; -const char TASK_INDEX[] = "AutoTest.Task.Index"; -const char UNNAMED_QUICKTESTS[] = QT_TR_NOOP(""); +const char ACTION_ID[] = "AutoTest.Action"; +const char MENU_ID[] = "AutoTest.Menu"; +const char AUTOTEST_ID[] = "AutoTest.ATP"; +const char AUTOTEST_CONTEXT[] = "Auto Tests"; +const char TASK_INDEX[] = "AutoTest.Task.Index"; +const char UNNAMED_QUICKTESTS[] = QT_TR_NOOP(""); +const char AUTOTEST_SETTINGS_CATEGORY[] = "ZY.Tests"; } // namespace Autotest } // namespace Constants diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index 065b561f5ff..2f99db04ae2 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -19,6 +19,8 @@ #include "autotestplugin.h" #include "autotestconstants.h" #include "testrunner.h" +#include "testsettings.h" +#include "testsettingspage.h" #include "testtreeview.h" #include "testtreemodel.h" #include "testresultspane.h" @@ -43,9 +45,13 @@ using namespace Autotest::Internal; +static AutotestPlugin *m_instance = 0; + AutotestPlugin::AutotestPlugin() + : m_settings(new TestSettings) { // Create your members + m_instance = this; } AutotestPlugin::~AutotestPlugin() @@ -58,6 +64,11 @@ AutotestPlugin::~AutotestPlugin() delete runner; } +AutotestPlugin *AutotestPlugin::instance() +{ + return m_instance; +} + bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorString) { // Register objects in the plugin manager's object pool @@ -90,6 +101,10 @@ bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorStri menu->addAction(cmd); Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu); + m_settings->fromSettings(Core::ICore::settings()); + TestSettingsPage *settingsPage = new TestSettingsPage(m_settings); + addAutoReleasedObject(settingsPage); + addAutoReleasedObject(new TestViewFactory); addAutoReleasedObject(TestResultsPane::instance()); diff --git a/plugins/autotest/autotestplugin.h b/plugins/autotest/autotestplugin.h index 6391f050feb..6d5365ddeea 100644 --- a/plugins/autotest/autotestplugin.h +++ b/plugins/autotest/autotestplugin.h @@ -26,6 +26,8 @@ namespace Autotest { namespace Internal { +struct TestSettings; + class AutotestPlugin : public ExtensionSystem::IPlugin { Q_OBJECT @@ -35,12 +37,19 @@ public: AutotestPlugin(); ~AutotestPlugin(); + static AutotestPlugin *instance(); + bool initialize(const QStringList &arguments, QString *errorString); void extensionsInitialized(); ShutdownFlag aboutToShutdown(); + QSharedPointer settings() const { return m_settings; } + private slots: void triggerAction(); + +private: + const QSharedPointer m_settings; }; } // namespace Internal diff --git a/plugins/autotest/images/autotest.png b/plugins/autotest/images/autotest.png new file mode 100644 index 0000000000000000000000000000000000000000..3f52e9bf08f153f408bdcf60bbf382d649796f87 GIT binary patch literal 683 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4rT@hhU+WOo?>8N3<&TEasB`QKLY~;Ljwat z0s})l7$tz&V3IMBktvahIf z<*UkT*VQ&`XlU8g(!Qm=b8Bb!_U`_j{S$Ugn7C`=q}`Jy@0mPx@6;LlXUyC`bMB$J z^AFEobac_u<4c#FShnKiiZ!R#tUtSc!?_I`&u!d(Y5R`LJN91Nd*H@_W4Di;ynFK8 zgL4-jUA*!9#@$zU@4vqP@Xf<#@1MQ+_~OmyH*deZegF0Shi@M~egE|N$LB9UzI^@p z_4}{yKY#!H_2<{`zrX+f`}^UtIM4p3*Lt5C8sKn_DL8&fi(P?%SDd zI{mUggm1@Z{Y>e(zUgd2G@~&Kmq3=Tv15kr>B~JTnJ+EBa+fjAm@abWLqK4Qo}Jrm z@rv9DN>4h(6pwZ-F+R35RP3hCAx%L~VIA-Ce$$)37jT=Gct}0)Nc>jn)6X5=qRP8@ zxnLUE3b5`eW`z-^I1?3dAj @@ -271,6 +273,11 @@ void TestResultsPane::onRunSelectedTriggered() void TestResultsPane::initializeFilterMenu() { + const bool omitIntern = AutotestPlugin::instance()->settings()->omitInternalMssg; + // FilterModel has all messages enabled by default + if (omitIntern) + m_filterModel->toggleTestResultType(ResultType::MESSAGE_INTERNAL); + QMap textAndType; textAndType.insert(ResultType::PASS, tr("Pass")); textAndType.insert(ResultType::FAIL, tr("Fail")); @@ -285,7 +292,7 @@ void TestResultsPane::initializeFilterMenu() QAction *action = new QAction(m_filterMenu); action->setText(textAndType.value(result)); action->setCheckable(true); - action->setChecked(true); + action->setChecked(result != ResultType::MESSAGE_INTERNAL || !omitIntern); action->setData(result); m_filterMenu->addAction(action); } diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 2c0b035a1c7..4ec7478453e 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -17,8 +17,10 @@ ****************************************************************************/ #include "autotestconstants.h" +#include "autotestplugin.h" #include "testresultspane.h" #include "testrunner.h" +#include "testsettings.h" #include // REMOVE @@ -112,6 +114,53 @@ static bool xmlExtractTypeFileLine(const QString &code, const QString &tagStart, return false; } +// adapted from qplaintestlogger.cpp +static QString formatResult(double value) +{ + if (value < 0 || value == NAN) + return QLatin1String("NAN"); + if (value == 0) + return QLatin1String("0"); + + int significantDigits = 0; + qreal divisor = 1; + + while (value / divisor >= 1) { + divisor *= 10; + ++significantDigits; + } + + QString beforeDecimalPoint = QString::number(value, 'f', 0); + QString afterDecimalPoint = QString::number(value, 'f', 20); + afterDecimalPoint.remove(0, beforeDecimalPoint.count() + 1); + + const int beforeUse = qMin(beforeDecimalPoint.count(), significantDigits); + const int beforeRemove = beforeDecimalPoint.count() - beforeUse; + + beforeDecimalPoint.chop(beforeRemove); + for (int i = 0; i < beforeRemove; ++i) + beforeDecimalPoint.append(QLatin1Char('0')); + + int afterUse = significantDigits - beforeUse; + if (beforeDecimalPoint == QLatin1String("0") && !afterDecimalPoint.isEmpty()) { + ++afterUse; + int i = 0; + while (i < afterDecimalPoint.count() && afterDecimalPoint.at(i) == QLatin1Char('0')) + ++i; + afterUse += i; + } + + const int afterRemove = afterDecimalPoint.count() - afterUse; + afterDecimalPoint.chop(afterRemove); + + QString result = beforeDecimalPoint; + if (afterUse > 0) + result.append(QLatin1Char('.')); + result += afterDecimalPoint; + + return result; +} + static bool xmlExtractBenchmarkInformation(const QString &code, const QString &tagStart, QString &description) { @@ -134,9 +183,9 @@ static bool xmlExtractBenchmarkInformation(const QString &code, const QString &t else if (metric == QLatin1String("CPUCycles")) // -perf metricsTxt = QLatin1String("CPU cycles"); description = QObject::tr("%1 %2 per iteration (total: %3, iterations: %4)") - .arg(QString::number(value, 'f', 6)) + .arg(formatResult(value)) .arg(metricsTxt) - .arg(QString::number(value * (double)iterations, 'g', 3)) + .arg(formatResult(value * (double)iterations)) .arg(iterations); return true; } @@ -282,7 +331,7 @@ static QString which(const QString &path, const QString &cmd) } bool performExec(const QString &cmd, const QStringList &args, const QString &workingDir, - const Utils::Environment &env, int timeout = 60000) + const Utils::Environment &env, int timeout) { QString runCmd; if (!QDir::toNativeSeparators(cmd).contains(QDir::separator())) { @@ -354,6 +403,10 @@ void performTestRun(QFutureInterface &future, const QList settings = AutotestPlugin::instance()->settings(); + const int timeout = settings->timeout; + const QString metricsOption = TestSettings::metricsTypeToOption(settings->metrics); + foreach (const TestConfiguration *tc, selectedTests) { if (future.isCanceled()) break; @@ -363,10 +416,12 @@ void performTestRun(QFutureInterface &future, const QListenvironment(); args << QLatin1String("-xml"); + if (!metricsOption.isEmpty()) + args << metricsOption; if (tc->testCases().count()) args << tc->testCases(); - performExec(cmd, args, workDir, env); + performExec(cmd, args, workDir, env, timeout); } future.setProgressValue(testCaseCount); diff --git a/plugins/autotest/testsettings.cpp b/plugins/autotest/testsettings.cpp new file mode 100644 index 00000000000..17a9f7c7aa5 --- /dev/null +++ b/plugins/autotest/testsettings.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "testsettings.h" + +#include + +namespace Autotest { +namespace Internal { + +static const char group[] = "Autotest"; +static const char timeoutKey[] = "Timeout"; +static const char metricsKey[] = "Metrics"; +static const char omitInternalKey[] = "OmitInternal"; +static const int defaultTimeout = 60000; + +TestSettings::TestSettings() + : timeout(defaultTimeout), metrics(Walltime), omitInternalMssg(true) +{ +} + +void TestSettings::toSettings(QSettings *s) const +{ + s->beginGroup(QLatin1String(group)); + s->setValue(QLatin1String(timeoutKey), timeout); + s->setValue(QLatin1String(metricsKey), metrics); + s->setValue(QLatin1String(omitInternalKey), omitInternalMssg); + s->endGroup(); +} + +static MetricsType intToMetrics(int value) +{ + switch (value) { + case Walltime: + return Walltime; + case TickCounter: + return TickCounter; + case EventCounter: + return EventCounter; + case CallGrind: + return CallGrind; + case Perf: + return Perf; + default: + return Walltime; + } +} + +void TestSettings::fromSettings(const QSettings *s) +{ + const QString root = QLatin1String(group) + QLatin1Char('/'); + timeout = s->value(root + QLatin1String(timeoutKey), defaultTimeout).toInt(); + metrics = intToMetrics(s->value(root + QLatin1String(metricsKey), Walltime).toInt()); + omitInternalMssg = s->value(root + QLatin1String(omitInternalKey), true).toBool(); +} + +bool TestSettings::equals(const TestSettings &rhs) const +{ + return timeout == rhs.timeout && metrics == rhs.metrics + && omitInternalMssg == rhs.omitInternalMssg; +} + +QString TestSettings::metricsTypeToOption(const MetricsType type) +{ + switch (type) { + case MetricsType::Walltime: + return QString(); + case MetricsType::TickCounter: + return QLatin1String("-tickcounter"); + case MetricsType::EventCounter: + return QLatin1String("-eventcounter"); + case MetricsType::CallGrind: + return QLatin1String("-callgrind"); + case MetricsType::Perf: + return QLatin1String("-perf"); + default: + return QString(); + } +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testsettings.h b/plugins/autotest/testsettings.h new file mode 100644 index 00000000000..dc82647d105 --- /dev/null +++ b/plugins/autotest/testsettings.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTSETTINGS_H +#define TESTSETTINGS_H + +#include + +QT_BEGIN_NAMESPACE +class QSettings; +QT_END_NAMESPACE + +namespace Autotest { +namespace Internal { + +enum MetricsType { + Walltime, + TickCounter, + EventCounter, + CallGrind, + Perf +}; + +struct TestSettings +{ + TestSettings(); + void toSettings(QSettings *s) const; + void fromSettings(const QSettings *s); + bool equals(const TestSettings &rhs) const; + static QString metricsTypeToOption(const MetricsType type); + + int timeout; + MetricsType metrics; + bool omitInternalMssg; +}; + +inline bool operator==(const TestSettings &s1, const TestSettings &s2) { return s1.equals(s2); } +inline bool operator!=(const TestSettings &s1, const TestSettings &s2) { return !s1.equals(s2); } + +} // namespace Internal +} // namespace Autotest + +#endif // TESTSETTINGS_H diff --git a/plugins/autotest/testsettingspage.cpp b/plugins/autotest/testsettingspage.cpp new file mode 100644 index 00000000000..64be40bb9be --- /dev/null +++ b/plugins/autotest/testsettingspage.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "autotestconstants.h" +#include "testsettingspage.h" +#include "testsettings.h" + +#include + +#include + +namespace Autotest { +namespace Internal { + +TestSettingsWidget::TestSettingsWidget(QWidget *parent) + : QWidget(parent) +{ + m_ui.setupUi(this); + m_ui.callgrindRB->setEnabled(Utils::HostOsInfo::isAnyUnixHost()); // valgrind available on UNIX + m_ui.perfRB->setEnabled(Utils::HostOsInfo::isLinuxHost()); // according to docs perf Linux only +} + +void TestSettingsWidget::setSettings(const TestSettings &settings) +{ + m_ui.timeoutSpin->setValue(settings.timeout / 1000); // we store milliseconds + m_ui.omitInternalMsgCB->setChecked(settings.omitInternalMssg); + + switch (settings.metrics) { + case MetricsType::Walltime: + m_ui.walltimeRB->setChecked(true); + break; + case MetricsType::TickCounter: + m_ui.tickcounterRB->setChecked(true); + break; + case MetricsType::EventCounter: + m_ui.eventCounterRB->setChecked(true); + break; + case MetricsType::CallGrind: + m_ui.callgrindRB->setChecked(true); + break; + case MetricsType::Perf: + m_ui.perfRB->setChecked(true); + break; + default: + m_ui.walltimeRB->setChecked(true); + } +} + +TestSettings TestSettingsWidget::settings() const +{ + TestSettings result; + result.timeout = m_ui.timeoutSpin->value() * 1000; // we display seconds + result.omitInternalMssg = m_ui.omitInternalMsgCB->isChecked(); + + if (m_ui.walltimeRB->isChecked()) + result.metrics = MetricsType::Walltime; + else if (m_ui.tickcounterRB->isChecked()) + result.metrics = MetricsType::TickCounter; + else if (m_ui.eventCounterRB->isChecked()) + result.metrics = MetricsType::EventCounter; + else if (m_ui.callgrindRB->isChecked()) + result.metrics = MetricsType::CallGrind; + else if (m_ui.perfRB->isChecked()) + result.metrics = MetricsType::Perf; + + return result; +} + +TestSettingsPage::TestSettingsPage(const QSharedPointer &settings) + : m_settings(settings), m_widget(0) +{ + setId("A.General"); + setDisplayName(tr("General")); + setCategory(Constants::AUTOTEST_SETTINGS_CATEGORY); + setDisplayCategory(tr("Test Settings")); + setCategoryIcon(QLatin1String(":/images/autotest.png")); +} + +TestSettingsPage::~TestSettingsPage() +{ +} + +QWidget *TestSettingsPage::widget() +{ + if (!m_widget) { + m_widget = new TestSettingsWidget; + m_widget->setSettings(*m_settings); + } + return m_widget; +} + +void TestSettingsPage::apply() +{ + if (!m_widget) // page was not shown at all + return; + const TestSettings newSettings = m_widget->settings(); + if (newSettings != *m_settings) { + *m_settings = newSettings; + m_settings->toSettings(Core::ICore::settings()); + } +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testsettingspage.h b/plugins/autotest/testsettingspage.h new file mode 100644 index 00000000000..cc30026fe27 --- /dev/null +++ b/plugins/autotest/testsettingspage.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTSETTINGSPAGE_H +#define TESTSETTINGSPAGE_H + +#include "ui_testsettingspage.h" + +#include + +#include + +namespace Autotest { +namespace Internal { + +struct TestSettings; + +class TestSettingsWidget : public QWidget +{ + Q_OBJECT +public: + explicit TestSettingsWidget(QWidget *parent = 0); + + void setSettings(const TestSettings &settings); + TestSettings settings() const; + +private: + Ui::TestSettingsPage m_ui; + +}; + +class TestSettingsPage : public Core::IOptionsPage +{ + Q_OBJECT +public: + explicit TestSettingsPage(const QSharedPointer &settings); + ~TestSettingsPage(); + + QWidget *widget(); + void apply(); + void finish() { } + +private: + QSharedPointer m_settings; + QPointer m_widget; +}; + +} // namespace Internal +} // namespace Autotest + +#endif // TESTSETTINGSPAGE_H diff --git a/plugins/autotest/testsettingspage.ui b/plugins/autotest/testsettingspage.ui new file mode 100644 index 00000000000..1a68db4b21b --- /dev/null +++ b/plugins/autotest/testsettingspage.ui @@ -0,0 +1,258 @@ + + + Autotest::Internal::TestSettingsPage + + + + 0 + 0 + 462 + 292 + + + + Form + + + + + + + + + + + + Timeout used when executing test cases. This will apply for each test case on its own, not the whole project. + + + Timeout: + + + + + + + Timeout used when executing test cases. This will apply for each test case on its own, not the whole project. + + + s + + + 5 + + + 36000 + + + 60 + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 40 + 20 + + + + + + + + If checked Internal Messages won't be shown by default. (You can still enable them on the test results filter) + + + Omit Internal Messages + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + + + 0 + 0 + + + + Benchmark Metrics + + + + + + + + + 0 + 0 + + + + Use Walltime metrics for executing benchmarks. (default) + + + Walltime + + + true + + + + + + + + 0 + 0 + + + + Use tick counter for executing benchmarks. + + + Tickcounter + + + + + + + + 0 + 0 + + + + Use event counter when executing benchmarks. + + + Eventcounter + + + + + + + false + + + + 0 + 0 + + + + Use callgrind when executing benchmark. (valgrind must be installed) + + + Callgrind + + + + + + + false + + + + 0 + 0 + + + + Use perf when executing benchmarks. (perf must be installed) + + + Perf + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + From ac24550a22ad59712e4cb5ea9955583c25101839 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 5 Dec 2014 14:01:16 +0100 Subject: [PATCH 026/200] Add special message to results pane This message just states which function actually is executed and will always be on the bottom of the list of results. When test run finishes this message will be completely removed. Change-Id: Ie8fedfc74f67eba71a2bcf55f4dc1553754fca9a Reviewed-by: Christian Stenger --- plugins/autotest/testresult.cpp | 4 +++ plugins/autotest/testresult.h | 1 + plugins/autotest/testresultmodel.cpp | 43 ++++++++++++++++++++++++---- plugins/autotest/testresultmodel.h | 1 + plugins/autotest/testresultspane.cpp | 1 + plugins/autotest/testrunner.cpp | 4 +++ 6 files changed, 48 insertions(+), 6 deletions(-) diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp index 175644d5701..2ade2c42ae6 100644 --- a/plugins/autotest/testresult.cpp +++ b/plugins/autotest/testresult.cpp @@ -86,6 +86,8 @@ ResultType TestResult::toResultType(int rt) return MESSAGE_FATAL; case MESSAGE_INTERNAL: return MESSAGE_INTERNAL; + case MESSAGE_CURRENT_TEST: + return MESSAGE_CURRENT_TEST; default: return UNKNOWN; } @@ -113,6 +115,7 @@ QString TestResult::resultToString(const ResultType type) case MESSAGE_FATAL: return QLatin1String("FATAL"); case MESSAGE_INTERNAL: + case MESSAGE_CURRENT_TEST: return QString(); case BLACKLISTED_PASS: return QLatin1String("BPASS"); @@ -147,6 +150,7 @@ QColor TestResult::colorForType(const ResultType type) case MESSAGE_FATAL: return QColor("#640000"); case MESSAGE_INTERNAL: + case MESSAGE_CURRENT_TEST: return QColor("transparent"); default: return QColor("#000000"); diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index 6ebcff9a6f8..86d3517a9d6 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -38,6 +38,7 @@ enum ResultType { MESSAGE_WARN, MESSAGE_FATAL, MESSAGE_INTERNAL, + MESSAGE_CURRENT_TEST, UNKNOWN // ??? }; diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index 8a5e8aca64b..78dbf1d8837 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -115,18 +115,48 @@ QVariant TestResultModel::data(const QModelIndex &index, int role) const void TestResultModel::addTestResult(const TestResult &testResult) { + const bool isCurrentTestMssg = testResult.result() == ResultType::MESSAGE_CURRENT_TEST; + const bool hasCurrentTestMssg = m_availableResultTypes.contains(ResultType::MESSAGE_CURRENT_TEST); + QReadLocker rLock(&m_rwLock); - beginInsertRows(QModelIndex(), m_testResults.size(), m_testResults.size()); + int position = m_testResults.size(); rLock.unlock(); + QWriteLocker wLock(&m_rwLock); - m_testResults.append(testResult); + if (hasCurrentTestMssg && isCurrentTestMssg) { + beginRemoveRows(QModelIndex(), position, position); + m_testResults.replace(position - 1, testResult); + endRemoveRows(); + } else { + if (!isCurrentTestMssg && position) // decrement only if at least one other item + --position; + beginInsertRows(QModelIndex(), position, position); + m_testResults.insert(position, testResult); + endInsertRows(); + } wLock.unlock(); - int count = m_testResultCount.value(testResult.result(), 0); - m_testResultCount.insert(testResult.result(), ++count); - endInsertRows(); + + if (!isCurrentTestMssg) { + int count = m_testResultCount.value(testResult.result(), 0); + m_testResultCount.insert(testResult.result(), ++count); + } + m_availableResultTypes.insert(testResult.result()); } +void TestResultModel::removeCurrentTestMessage() +{ + QReadLocker rLock(&m_rwLock); + if (m_availableResultTypes.contains(ResultType::MESSAGE_CURRENT_TEST)) { + rLock.unlock(); + QWriteLocker wLock(&m_rwLock); + beginRemoveRows(QModelIndex(), m_testResults.size() - 1, m_testResults.size() - 1); + m_testResults.removeLast(); + endRemoveRows(); + m_availableResultTypes.remove(ResultType::MESSAGE_CURRENT_TEST); + } +} + void TestResultModel::clearTestResults() { QReadLocker rLock(&m_rwLock); @@ -211,7 +241,8 @@ void TestResultFilterModel::enableAllResultTypes() << ResultType::UNEXPECTED_PASS << ResultType::SKIP << ResultType::MESSAGE_DEBUG << ResultType::MESSAGE_WARN << ResultType::MESSAGE_INTERNAL << ResultType::MESSAGE_FATAL << ResultType::UNKNOWN << ResultType::BLACKLISTED_PASS - << ResultType::BLACKLISTED_FAIL << ResultType::BENCHMARK; + << ResultType::BLACKLISTED_FAIL << ResultType::BENCHMARK + << ResultType::MESSAGE_CURRENT_TEST; invalidateFilter(); } diff --git a/plugins/autotest/testresultmodel.h b/plugins/autotest/testresultmodel.h index 1ef019a4567..7494161bb7a 100644 --- a/plugins/autotest/testresultmodel.h +++ b/plugins/autotest/testresultmodel.h @@ -43,6 +43,7 @@ public: QVariant data(const QModelIndex &index, int role) const; void addTestResult(const TestResult &testResult); + void removeCurrentTestMessage(); void clearTestResults(); bool hasResults() const { return m_testResults.size() > 0; } diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index cb28412a4c9..6d902705f1c 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -370,6 +370,7 @@ void TestResultsPane::onTestRunFinished() m_runSelected->setEnabled(true); updateSummaryLabel(); m_summaryWidget->setVisible(true); + m_model->removeCurrentTestMessage(); } void TestResultsPane::onTestTreeModelChanged() diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 4ec7478453e..f3f7e371439 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -228,6 +228,10 @@ void processOutput() result = ResultType::UNKNOWN; lineNumber = 0; readingDescription = false; + TestResultsPane::instance()->addTestResult( + TestResult(className, testCase, QString(), ResultType::MESSAGE_CURRENT_TEST, + QObject::tr("Entering Test Function %1::%2") + .arg(className).arg(testCase))); continue; } if (xmlStartsWith(line, QLatin1String(" Date: Tue, 9 Dec 2014 14:02:41 +0100 Subject: [PATCH 027/200] Re-do the usage of QWriteLocker Only lock if necessary to avoid dead-lock situations. Change-Id: I39d1158749131a72805e55f28aba79e1827f158b Reviewed-by: Christian Stenger --- plugins/autotest/testresultmodel.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index 78dbf1d8837..6ccc3946ffd 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -54,7 +54,7 @@ QModelIndex TestResultModel::parent(const QModelIndex &) const int TestResultModel::rowCount(const QModelIndex &parent) const { - // do not use the QReadLocker here or this will produce a deadlock + QReadLocker lock(&m_rwLock); return parent.isValid() ? 0 : m_testResults.size(); } @@ -122,19 +122,21 @@ void TestResultModel::addTestResult(const TestResult &testResult) int position = m_testResults.size(); rLock.unlock(); - QWriteLocker wLock(&m_rwLock); if (hasCurrentTestMssg && isCurrentTestMssg) { beginRemoveRows(QModelIndex(), position, position); + QWriteLocker wLock(&m_rwLock); m_testResults.replace(position - 1, testResult); + wLock.unlock(); endRemoveRows(); } else { if (!isCurrentTestMssg && position) // decrement only if at least one other item --position; beginInsertRows(QModelIndex(), position, position); + QWriteLocker wLock(&m_rwLock); m_testResults.insert(position, testResult); + wLock.unlock(); endInsertRows(); } - wLock.unlock(); if (!isCurrentTestMssg) { int count = m_testResultCount.value(testResult.result(), 0); @@ -148,10 +150,11 @@ void TestResultModel::removeCurrentTestMessage() { QReadLocker rLock(&m_rwLock); if (m_availableResultTypes.contains(ResultType::MESSAGE_CURRENT_TEST)) { + beginRemoveRows(QModelIndex(), m_testResults.size() - 1, m_testResults.size() - 1); rLock.unlock(); QWriteLocker wLock(&m_rwLock); - beginRemoveRows(QModelIndex(), m_testResults.size() - 1, m_testResults.size() - 1); m_testResults.removeLast(); + wLock.unlock(); endRemoveRows(); m_availableResultTypes.remove(ResultType::MESSAGE_CURRENT_TEST); } From 59a4999de3d3f1109397bf151a1671830461d176 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Thu, 18 Dec 2014 12:22:06 +0100 Subject: [PATCH 028/200] rename pro file to subdirectory name Change-Id: I7636e819f41a3fc0592a36f330f30695760cad6a Reviewed-by: Christian Stenger --- autotest.pro => autotest-qtcreator-plugin.pro | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename autotest.pro => autotest-qtcreator-plugin.pro (100%) diff --git a/autotest.pro b/autotest-qtcreator-plugin.pro similarity index 100% rename from autotest.pro rename to autotest-qtcreator-plugin.pro From 19f36ebf7822533ed9c775991115ddcc260573e0 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Thu, 18 Dec 2014 12:48:18 +0100 Subject: [PATCH 029/200] rename selectOrDeselectAll to changeCheckStateAll Change-Id: I78e700734e2b5ec6bad31df71419bbc1a8b1b3c8 Reviewed-by: Christian Stenger --- plugins/autotest/testtreeview.cpp | 6 +++--- plugins/autotest/testtreeview.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/autotest/testtreeview.cpp b/plugins/autotest/testtreeview.cpp index fdd3ee40966..22632acafe8 100644 --- a/plugins/autotest/testtreeview.cpp +++ b/plugins/autotest/testtreeview.cpp @@ -243,16 +243,16 @@ TestTreeView::TestTreeView(QWidget *parent) void TestTreeView::selectAll() { - selectOrDeselectAll(Qt::Checked); + changeCheckStateAll(Qt::Checked); } void TestTreeView::deselectAll() { - selectOrDeselectAll(Qt::Unchecked); + changeCheckStateAll(Qt::Unchecked); } // this avoids the re-evaluation of parent nodes when modifying the child nodes (setData()) -void TestTreeView::selectOrDeselectAll(const Qt::CheckState checkState) +void TestTreeView::changeCheckStateAll(const Qt::CheckState checkState) { const TestTreeModel *model = TestTreeModel::instance(); diff --git a/plugins/autotest/testtreeview.h b/plugins/autotest/testtreeview.h index 5f6c8670adf..e9252ab136b 100644 --- a/plugins/autotest/testtreeview.h +++ b/plugins/autotest/testtreeview.h @@ -51,7 +51,7 @@ public: void deselectAll(); private: - void selectOrDeselectAll(const Qt::CheckState checkState); + void changeCheckStateAll(const Qt::CheckState checkState); Core::IContext *m_context; }; From d778fc5477ae311f7207241ef73459eafae2c83e Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 10 Dec 2014 09:41:23 +0100 Subject: [PATCH 030/200] Post-pone parsing for test if CppModelManager is parsing Change-Id: I7af93eb587e55f7d6e4ee14ed9808ceeb41ed8a3 Reviewed-by: Tim Jenssen --- plugins/autotest/testcodeparser.cpp | 44 ++++++++++++++++++++++++++++- plugins/autotest/testcodeparser.h | 9 ++++++ plugins/autotest/testtreeview.cpp | 2 +- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index a0ba1534ce3..e2d342cb486 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -23,15 +23,20 @@ #include "testtreemodel.h" #include "testvisitor.h" +#include + #include #include +#include #include #include #include #include +#include + #include #include #include @@ -44,8 +49,15 @@ namespace Internal { TestCodeParser::TestCodeParser(TestTreeModel *parent) : QObject(parent), m_model(parent), - m_currentProject(0) + m_currentProject(0), + m_parserEnabled(true), + m_pendingUpdate(false) { + // connect to ProgressManager to post-pone test parsing when CppModelManager is parsing + Core::ProgressManager *pm = qobject_cast( + Core::ProgressManager::instance()); + connect(pm, &Core::ProgressManager::taskStarted, this, &TestCodeParser::onTaskStarted); + connect(pm, &Core::ProgressManager::allTasksFinished, this, &TestCodeParser::onAllTasksFinished); } TestCodeParser::~TestCodeParser() @@ -53,8 +65,19 @@ TestCodeParser::~TestCodeParser() clearMaps(); } +void TestCodeParser::emitUpdateTestTree() +{ + QTimer::singleShot(1000, this, SLOT(updateTestTree())); +} + void TestCodeParser::updateTestTree() { + if (!m_parserEnabled) { + m_pendingUpdate = true; + qDebug() << "Skipped update due to running parser or pro file evaluate"; + return; + } + qDebug("updating TestTreeModel"); clearMaps(); @@ -84,6 +107,7 @@ void TestCodeParser::updateTestTree() } } scanForTests(); + m_pendingUpdate = false; } /****** scan for QTest related stuff helpers ******/ @@ -721,6 +745,24 @@ void TestCodeParser::removeTestsIfNecessaryByProFile(const QString &proFile) m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), unnamedInfo); } +void TestCodeParser::onTaskStarted(Core::Id type) +{ + if (type != CppTools::Constants::TASK_INDEX + && type != QmakeProjectManager::Constants::PROFILE_EVALUATE) + return; + m_parserEnabled = false; +} + +void TestCodeParser::onAllTasksFinished(Core::Id type) +{ + if (type != CppTools::Constants::TASK_INDEX + && type != QmakeProjectManager::Constants::PROFILE_EVALUATE) + return; + m_parserEnabled = true; + if (m_pendingUpdate) + updateTestTree(); +} + void TestCodeParser::onProFileEvaluated() { if (!m_currentProject) diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index da89eb51d7f..02556243f61 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -30,6 +30,10 @@ namespace ProjectExplorer { class Project; } +namespace Core { +class Id; +} + namespace Autotest { namespace Internal { @@ -46,6 +50,7 @@ public: signals: public slots: + void emitUpdateTestTree(); void updateTestTree(); void checkDocumentForTestCode(CPlusPlus::Document::Ptr doc); void handleQtQuickTest(CPlusPlus::Document::Ptr doc); @@ -60,11 +65,15 @@ private: void clearMaps(); void removeTestsIfNecessary(const QString &fileName); void removeTestsIfNecessaryByProFile(const QString &proFile); + void onTaskStarted(Core::Id type); + void onAllTasksFinished(Core::Id type); TestTreeModel *m_model; QMap m_cppDocMap; QMap m_quickDocMap; ProjectExplorer::Project *m_currentProject; + bool m_parserEnabled; + bool m_pendingUpdate; }; } // namespace Internal diff --git a/plugins/autotest/testtreeview.cpp b/plugins/autotest/testtreeview.cpp index 22632acafe8..9aa7422a941 100644 --- a/plugins/autotest/testtreeview.cpp +++ b/plugins/autotest/testtreeview.cpp @@ -65,7 +65,7 @@ TestTreeViewWidget::TestTreeViewWidget(QWidget *parent) : TestCodeParser *parser = m_model->parser(); ProjectExplorer::SessionManager *sm = ProjectExplorer::SessionManager::instance(); connect(sm, &ProjectExplorer::SessionManager::startupProjectChanged, - parser, &TestCodeParser::updateTestTree); + parser, &TestCodeParser::emitUpdateTestTree); CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); connect(cppMM, &CppTools::CppModelManager::documentUpdated, From 6a4afc7d5f8bb90582fa0e6e68c97448ded29b79 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Thu, 18 Dec 2014 15:02:07 +0100 Subject: [PATCH 031/200] rename TestTreeViewWidget to TestNavigationWidget also move it to an extra file Change-Id: Ia76c9b3be4c11207a564e7cc7fcb2eae730ae505 Reviewed-by: Christian Stenger --- plugins/autotest/autotest.pro | 6 +- plugins/autotest/autotestplugin.cpp | 3 +- plugins/autotest/testnavigationwidget.cpp | 230 ++++++++++++++++++++++ plugins/autotest/testnavigationwidget.h | 91 +++++++++ plugins/autotest/testtreeview.cpp | 187 ------------------ plugins/autotest/testtreeview.h | 58 ------ 6 files changed, 327 insertions(+), 248 deletions(-) create mode 100644 plugins/autotest/testnavigationwidget.cpp create mode 100644 plugins/autotest/testnavigationwidget.h diff --git a/plugins/autotest/autotest.pro b/plugins/autotest/autotest.pro index 507d9303003..0366ffae461 100644 --- a/plugins/autotest/autotest.pro +++ b/plugins/autotest/autotest.pro @@ -24,7 +24,8 @@ SOURCES += \ testresultdelegate.cpp \ testtreeitemdelegate.cpp \ testsettings.cpp \ - testsettingspage.cpp + testsettingspage.cpp \ + testnavigationwidget.cpp HEADERS += \ testtreeview.h \ @@ -44,7 +45,8 @@ HEADERS += \ testresultdelegate.h \ testtreeitemdelegate.h \ testsettings.h \ - testsettingspage.h + testsettingspage.h \ + testnavigationwidget.h RESOURCES += \ autotest.qrc diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index 2f99db04ae2..2abcebbb801 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -24,6 +24,7 @@ #include "testtreeview.h" #include "testtreemodel.h" #include "testresultspane.h" +#include "testnavigationwidget.h" #include #include @@ -105,7 +106,7 @@ bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorStri TestSettingsPage *settingsPage = new TestSettingsPage(m_settings); addAutoReleasedObject(settingsPage); - addAutoReleasedObject(new TestViewFactory); + addAutoReleasedObject(new TestNavigationWidgetFactory); addAutoReleasedObject(TestResultsPane::instance()); return true; diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp new file mode 100644 index 00000000000..0f1fca7a41e --- /dev/null +++ b/plugins/autotest/testnavigationwidget.cpp @@ -0,0 +1,230 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "testnavigationwidget.h" +#include "testtreemodel.h" +#include "testtreeview.h" +#include "testtreeitemdelegate.h" +#include "testcodeparser.h" +#include "testrunner.h" +#include "autotestconstants.h" +#include "testtreeitem.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace Autotest { +namespace Internal { + +TestNavigationWidget::TestNavigationWidget(QWidget *parent) : + QWidget(parent) +{ + setWindowTitle(tr("Tests")); + m_model = TestTreeModel::instance(); + m_sortFilterModel = new TestTreeSortFilterModel(m_model, m_model); + m_sortFilterModel->setDynamicSortFilter(true); + m_view = new TestTreeView(this); + m_view->setModel(m_sortFilterModel); + m_view->setSortingEnabled(true); + m_view->setItemDelegate(new TestTreeItemDelegate(this)); + + QVBoxLayout *layout = new QVBoxLayout; + layout->setMargin(0); + layout->setSpacing(0); + layout->addWidget(Core::ItemViewFind::createSearchableWrapper(m_view)); + setLayout(layout); + + TestCodeParser *parser = m_model->parser(); + ProjectExplorer::SessionManager *sm = ProjectExplorer::SessionManager::instance(); + connect(sm, &ProjectExplorer::SessionManager::startupProjectChanged, + parser, &TestCodeParser::emitUpdateTestTree); + + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + connect(cppMM, &CppTools::CppModelManager::documentUpdated, + parser, &TestCodeParser::onCppDocumentUpdated, Qt::QueuedConnection); + connect(cppMM, &CppTools::CppModelManager::aboutToRemoveFiles, + parser, &TestCodeParser::removeFiles, Qt::QueuedConnection); + + QmlJS::ModelManagerInterface *qmlJsMM = QmlJSTools::Internal::ModelManager::instance(); + connect(qmlJsMM, &QmlJS::ModelManagerInterface::documentUpdated, + parser, &TestCodeParser::onQmlDocumentUpdated, Qt::QueuedConnection); + connect(qmlJsMM, &QmlJS::ModelManagerInterface::aboutToRemoveFiles, + parser, &TestCodeParser::removeFiles, Qt::QueuedConnection); + + connect(m_view, &TestTreeView::activated, this, &TestNavigationWidget::onItemActivated); +} + +void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event) +{ + const bool enabled = !TestRunner::instance()->isTestRunning(); + const bool hasTests = m_model->hasTests(); + QMenu menu; + QAction *runAll = new QAction(tr("Run All Tests"), &menu); + QAction *runSelected = new QAction(tr("Run Selected Tests"), &menu); + QAction *selectAll = new QAction(tr("Select All"), &menu); + QAction *deselectAll = new QAction(tr("Deselect All"), &menu); + // TODO remove? + QAction *rescan = new QAction(tr("Rescan"), &menu); + + connect(runAll, &QAction::triggered, this, &TestNavigationWidget::onRunAllTriggered); + connect(runSelected, &QAction::triggered, this, &TestNavigationWidget::onRunSelectedTriggered); + connect(selectAll, &QAction::triggered, m_view, &TestTreeView::selectAll); + connect(deselectAll, &QAction::triggered, m_view, &TestTreeView::deselectAll); + connect(rescan, &QAction::triggered, TestTreeModel::instance()->parser(), + &TestCodeParser::updateTestTree); + + runAll->setEnabled(enabled && hasTests); + runSelected->setEnabled(enabled && hasTests); + selectAll->setEnabled(enabled && hasTests); + deselectAll->setEnabled(enabled && hasTests); + rescan->setEnabled(enabled); + + menu.addAction(runAll); + menu.addAction(runSelected); + menu.addSeparator(); + menu.addAction(selectAll); + menu.addAction(deselectAll); + menu.addSeparator(); + menu.addAction(rescan); + + menu.exec(mapToGlobal(event->pos())); +} + +QList TestNavigationWidget::createToolButtons() +{ + QList list; + + m_filterButton = new QToolButton(m_view); + m_filterButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_FILTER))); + m_filterButton->setToolTip(tr("Filter Test Tree")); + m_filterButton->setProperty("noArrow", true); + m_filterButton->setAutoRaise(true); + m_filterButton->setPopupMode(QToolButton::InstantPopup); + m_filterMenu = new QMenu(m_filterButton); + initializeFilterMenu(); + connect(m_filterMenu, &QMenu::triggered, this, &TestNavigationWidget::onFilterMenuTriggered); + m_filterButton->setMenu(m_filterMenu); + + m_sortAlphabetically = true; + m_sort = new QToolButton(this); + m_sort->setIcon((QIcon(QLatin1String(":/images/leafsort.png")))); + m_sort->setToolTip(tr("Sort Naturally")); + + QToolButton *expand = new QToolButton(this); + expand->setIcon(QIcon(QLatin1String(":/images/expand.png"))); + expand->setToolTip(tr("Expand All")); + + QToolButton *collapse = new QToolButton(this); + collapse->setIcon(QIcon(QLatin1String(":/images/collapse.png"))); + collapse->setToolTip(tr("Collapse All")); + + connect(expand, &QToolButton::clicked, m_view, &TestTreeView::expandAll); + connect(collapse, &QToolButton::clicked, m_view, &TestTreeView::collapseAll); + connect(m_sort, &QToolButton::clicked, this, &TestNavigationWidget::onSortClicked); + + list << m_filterButton << m_sort << expand << collapse; + return list; +} + +void TestNavigationWidget::onItemActivated(const QModelIndex &index) +{ + const TextEditor::TextEditorWidget::Link link + = index.data(LinkRole).value(); + if (link.hasValidTarget()) { + Core::EditorManager::openEditorAt(link.targetFileName, link.targetLine, + link.targetColumn); + } +} + +void TestNavigationWidget::onRunAllTriggered() +{ + TestRunner *runner = TestRunner::instance(); + runner->setSelectedTests(m_model->getAllTestCases()); + runner->runTests(); +} + +void TestNavigationWidget::onRunSelectedTriggered() +{ + TestRunner *runner = TestRunner::instance(); + runner->setSelectedTests(m_model->getSelectedTests()); + runner->runTests(); +} + +void TestNavigationWidget::onSortClicked() +{ + if (m_sortAlphabetically) { + m_sort->setIcon((QIcon(QLatin1String(":/images/sort.png")))); + m_sort->setToolTip(tr("Sort Alphabetically")); + m_sortFilterModel->setSortMode(TestTreeSortFilterModel::Naturally); + } else { + m_sort->setIcon((QIcon(QLatin1String(":/images/leafsort.png")))); + m_sort->setToolTip(tr("Sort Naturally")); + m_sortFilterModel->setSortMode(TestTreeSortFilterModel::Alphabetically); + } + m_sortAlphabetically = !m_sortAlphabetically; +} + +void TestNavigationWidget::onFilterMenuTriggered(QAction *action) +{ + m_sortFilterModel->toggleFilter( + TestTreeSortFilterModel::toFilterMode(action->data().value())); +} + +void TestNavigationWidget::initializeFilterMenu() +{ + QAction *action = new QAction(m_filterMenu); + action->setText(tr("Show init and cleanup functions")); + action->setCheckable(true); + action->setChecked(false); + action->setData(TestTreeSortFilterModel::ShowInitAndCleanup); + m_filterMenu->addAction(action); + action = new QAction(m_filterMenu); + action->setText(tr("Show data functions")); + action->setCheckable(true); + action->setChecked(false); + action->setData(TestTreeSortFilterModel::ShowTestData); + m_filterMenu->addAction(action); +} + +TestNavigationWidgetFactory::TestNavigationWidgetFactory() +{ + setDisplayName(tr("Tests")); + setId(Autotest::Constants::AUTOTEST_ID); + setPriority(666); +} + +Core::NavigationView TestNavigationWidgetFactory::createWidget() +{ + TestNavigationWidget *treeViewWidget = new TestNavigationWidget; + Core::NavigationView view; + view.widget = treeViewWidget; + view.dockToolBarWidgets = treeViewWidget->createToolButtons(); + return view; +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testnavigationwidget.h b/plugins/autotest/testnavigationwidget.h new file mode 100644 index 00000000000..2700cf2c125 --- /dev/null +++ b/plugins/autotest/testnavigationwidget.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTNAVIGATIONWIDGETTREEVIEW_H +#define TESTNAVIGATIONWIDGETTREEVIEW_H + +#include + +#include + +QT_BEGIN_NAMESPACE +class QAction; +class QMenu; +class QToolButton; +QT_END_NAMESPACE + +namespace Core { +class IContext; +} + +namespace Autotest { +namespace Internal { + +class TestTreeModel; +class TestTreeSortFilterModel; +class TestTreeView; + +class TestNavigationWidget : public QWidget +{ + Q_OBJECT + +public: + explicit TestNavigationWidget(QWidget *parent = 0); + void contextMenuEvent(QContextMenuEvent *event); + QList createToolButtons(); + +signals: + +public slots: + +private slots: + void onItemActivated(const QModelIndex &index); + void onRunAllTriggered(); + void onRunSelectedTriggered(); + void onSortClicked(); + void onFilterMenuTriggered(QAction *action); + +private: + void initializeFilterMenu(); + + TestTreeModel *m_model; + TestTreeSortFilterModel *m_sortFilterModel; + TestTreeView *m_view; + QToolButton *m_sort; + QToolButton *m_filterButton; + QMenu *m_filterMenu; + bool m_sortAlphabetically; + +}; + +class TestNavigationWidgetFactory : public Core::INavigationWidgetFactory +{ + Q_OBJECT + +public: + TestNavigationWidgetFactory(); + +private: + Core::NavigationView createWidget(); + +}; + +} // namespace Internal +} // namespace Autotest + +#endif // TESTNAVIGATIONWIDGETTREEVIEW_H diff --git a/plugins/autotest/testtreeview.cpp b/plugins/autotest/testtreeview.cpp index 9aa7422a941..704067a6371 100644 --- a/plugins/autotest/testtreeview.cpp +++ b/plugins/autotest/testtreeview.cpp @@ -44,193 +44,6 @@ namespace Autotest { namespace Internal { -TestTreeViewWidget::TestTreeViewWidget(QWidget *parent) : - QWidget(parent) -{ - setWindowTitle(tr("Tests")); - m_model = TestTreeModel::instance(); - m_sortFilterModel = new TestTreeSortFilterModel(m_model, m_model); - m_sortFilterModel->setDynamicSortFilter(true); - m_view = new TestTreeView(this); - m_view->setModel(m_sortFilterModel); - m_view->setSortingEnabled(true); - m_view->setItemDelegate(new TestTreeItemDelegate(this)); - - QVBoxLayout *layout = new QVBoxLayout; - layout->setMargin(0); - layout->setSpacing(0); - layout->addWidget(Core::ItemViewFind::createSearchableWrapper(m_view)); - setLayout(layout); - - TestCodeParser *parser = m_model->parser(); - ProjectExplorer::SessionManager *sm = ProjectExplorer::SessionManager::instance(); - connect(sm, &ProjectExplorer::SessionManager::startupProjectChanged, - parser, &TestCodeParser::emitUpdateTestTree); - - CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); - connect(cppMM, &CppTools::CppModelManager::documentUpdated, - parser, &TestCodeParser::onCppDocumentUpdated, Qt::QueuedConnection); - connect(cppMM, &CppTools::CppModelManager::aboutToRemoveFiles, - parser, &TestCodeParser::removeFiles, Qt::QueuedConnection); - - QmlJS::ModelManagerInterface *qmlJsMM = QmlJSTools::Internal::ModelManager::instance(); - connect(qmlJsMM, &QmlJS::ModelManagerInterface::documentUpdated, - parser, &TestCodeParser::onQmlDocumentUpdated, Qt::QueuedConnection); - connect(qmlJsMM, &QmlJS::ModelManagerInterface::aboutToRemoveFiles, - parser, &TestCodeParser::removeFiles, Qt::QueuedConnection); - - connect(m_view, &TestTreeView::activated, this, &TestTreeViewWidget::onItemActivated); -} - -void TestTreeViewWidget::contextMenuEvent(QContextMenuEvent *event) -{ - const bool enabled = !TestRunner::instance()->isTestRunning(); - const bool hasTests = m_model->hasTests(); - QMenu menu; - QAction *runAll = new QAction(tr("Run All Tests"), &menu); - QAction *runSelected = new QAction(tr("Run Selected Tests"), &menu); - QAction *selectAll = new QAction(tr("Select All"), &menu); - QAction *deselectAll = new QAction(tr("Deselect All"), &menu); - // TODO remove? - QAction *rescan = new QAction(tr("Rescan"), &menu); - - connect(runAll, &QAction::triggered, this, &TestTreeViewWidget::onRunAllTriggered); - connect(runSelected, &QAction::triggered, this, &TestTreeViewWidget::onRunSelectedTriggered); - connect(selectAll, &QAction::triggered, m_view, &TestTreeView::selectAll); - connect(deselectAll, &QAction::triggered, m_view, &TestTreeView::deselectAll); - connect(rescan, &QAction::triggered, - TestTreeModel::instance()->parser(), &TestCodeParser::updateTestTree); - - runAll->setEnabled(enabled && hasTests); - runSelected->setEnabled(enabled && hasTests); - selectAll->setEnabled(enabled && hasTests); - deselectAll->setEnabled(enabled && hasTests); - rescan->setEnabled(enabled); - - menu.addAction(runAll); - menu.addAction(runSelected); - menu.addSeparator(); - menu.addAction(selectAll); - menu.addAction(deselectAll); - menu.addSeparator(); - menu.addAction(rescan); - - menu.exec(mapToGlobal(event->pos())); -} - -QList TestTreeViewWidget::createToolButtons() -{ - QList list; - - m_filterButton = new QToolButton(m_view); - m_filterButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_FILTER))); - m_filterButton->setToolTip(tr("Filter Test Tree")); - m_filterButton->setProperty("noArrow", true); - m_filterButton->setAutoRaise(true); - m_filterButton->setPopupMode(QToolButton::InstantPopup); - m_filterMenu = new QMenu(m_filterButton); - initializeFilterMenu(); - connect(m_filterMenu, &QMenu::triggered, this, &TestTreeViewWidget::onFilterMenuTriggered); - m_filterButton->setMenu(m_filterMenu); - - m_sortAlphabetically = true; - m_sort = new QToolButton(this); - m_sort->setIcon((QIcon(QLatin1String(":/images/leafsort.png")))); - m_sort->setToolTip(tr("Sort Naturally")); - - QToolButton *expand = new QToolButton(this); - expand->setIcon(QIcon(QLatin1String(":/images/expand.png"))); - expand->setToolTip(tr("Expand All")); - - QToolButton *collapse = new QToolButton(this); - collapse->setIcon(QIcon(QLatin1String(":/images/collapse.png"))); - collapse->setToolTip(tr("Collapse All")); - - connect(expand, &QToolButton::clicked, m_view, &TestTreeView::expandAll); - connect(collapse, &QToolButton::clicked, m_view, &TestTreeView::collapseAll); - connect(m_sort, &QToolButton::clicked, this, &TestTreeViewWidget::onSortClicked); - - list << m_filterButton << m_sort << expand << collapse; - return list; -} - -void TestTreeViewWidget::onItemActivated(const QModelIndex &index) -{ - const TextEditor::TextEditorWidget::Link link - = index.data(LinkRole).value(); - if (link.hasValidTarget()) { - Core::EditorManager::openEditorAt(link.targetFileName, - link.targetLine, - link.targetColumn); - } -} - -void TestTreeViewWidget::onRunAllTriggered() -{ - TestRunner *runner = TestRunner::instance(); - runner->setSelectedTests(m_model->getAllTestCases()); - runner->runTests(); -} - -void TestTreeViewWidget::onRunSelectedTriggered() -{ - TestRunner *runner = TestRunner::instance(); - runner->setSelectedTests(m_model->getSelectedTests()); - runner->runTests(); -} - -void TestTreeViewWidget::onSortClicked() -{ - if (m_sortAlphabetically) { - m_sort->setIcon((QIcon(QLatin1String(":/images/sort.png")))); - m_sort->setToolTip(tr("Sort Alphabetically")); - m_sortFilterModel->setSortMode(TestTreeSortFilterModel::Naturally); - } else { - m_sort->setIcon((QIcon(QLatin1String(":/images/leafsort.png")))); - m_sort->setToolTip(tr("Sort Naturally")); - m_sortFilterModel->setSortMode(TestTreeSortFilterModel::Alphabetically); - } - m_sortAlphabetically = !m_sortAlphabetically; -} - -void TestTreeViewWidget::onFilterMenuTriggered(QAction *action) -{ - m_sortFilterModel->toggleFilter( - TestTreeSortFilterModel::toFilterMode(action->data().value())); -} - -void TestTreeViewWidget::initializeFilterMenu() -{ - QAction *action = new QAction(m_filterMenu); - action->setText(tr("Show init and cleanup functions")); - action->setCheckable(true); - action->setChecked(false); - action->setData(TestTreeSortFilterModel::ShowInitAndCleanup); - m_filterMenu->addAction(action); - action = new QAction(m_filterMenu); - action->setText(tr("Show data functions")); - action->setCheckable(true); - action->setChecked(false); - action->setData(TestTreeSortFilterModel::ShowTestData); - m_filterMenu->addAction(action); -} - -TestViewFactory::TestViewFactory() -{ - setDisplayName(tr("Tests")); - setId(Autotest::Constants::AUTOTEST_ID); - setPriority(666); -} - -Core::NavigationView TestViewFactory::createWidget() -{ - TestTreeViewWidget *treeViewWidget = new TestTreeViewWidget; - Core::NavigationView view; - view.widget = treeViewWidget; - view.dockToolBarWidgets = treeViewWidget->createToolButtons(); - return view; -} - TestTreeView::TestTreeView(QWidget *parent) : NavigationTreeView(parent), m_context(new Core::IContext(this)) diff --git a/plugins/autotest/testtreeview.h b/plugins/autotest/testtreeview.h index e9252ab136b..9865e69df27 100644 --- a/plugins/autotest/testtreeview.h +++ b/plugins/autotest/testtreeview.h @@ -19,17 +19,8 @@ #ifndef TESTTREEVIEW_H #define TESTTREEVIEW_H -#include - #include -QT_BEGIN_NAMESPACE -class QAction; -class QMenu; -class QModelIndex; -class QToolButton; -QT_END_NAMESPACE - namespace Core { class IContext; } @@ -37,9 +28,6 @@ class IContext; namespace Autotest { namespace Internal { -class TestTreeModel; -class TestTreeSortFilterModel; - class TestTreeView : public Utils::NavigationTreeView { Q_OBJECT @@ -55,52 +43,6 @@ private: Core::IContext *m_context; }; - -class TestTreeViewWidget : public QWidget -{ - Q_OBJECT - -public: - explicit TestTreeViewWidget(QWidget *parent = 0); - void contextMenuEvent(QContextMenuEvent *event); - QList createToolButtons(); - -signals: - -public slots: - -private slots: - void onItemActivated(const QModelIndex &index); - void onRunAllTriggered(); - void onRunSelectedTriggered(); - void onSortClicked(); - void onFilterMenuTriggered(QAction *action); - -private: - void initializeFilterMenu(); - - TestTreeModel *m_model; - TestTreeSortFilterModel *m_sortFilterModel; - TestTreeView *m_view; - QToolButton *m_sort; - QToolButton *m_filterButton; - QMenu *m_filterMenu; - bool m_sortAlphabetically; - -}; - -class TestViewFactory : public Core::INavigationWidgetFactory -{ - Q_OBJECT - -public: - TestViewFactory(); - -private: - Core::NavigationView createWidget(); - -}; - } // namespace Internal } // namespace Autotest From 2cc47c2039c4b78c2f14b268ef156afd90255843 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Thu, 18 Dec 2014 17:35:25 +0100 Subject: [PATCH 032/200] move license check to a function Change-Id: Idcb2c328f3313dac38997765c2569d6861d34a20 Reviewed-by: Christian Stenger --- plugins/autotest/autotestplugin.cpp | 21 ++++++++++++++------- plugins/autotest/autotestplugin.h | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index 2abcebbb801..7823fdef2c0 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -70,6 +70,19 @@ AutotestPlugin *AutotestPlugin::instance() return m_instance; } +bool AutotestPlugin::checkLicense() +{ + LicenseChecker::LicenseCheckerPlugin *licenseChecker + = ExtensionSystem::PluginManager::getObject(); + + if (!licenseChecker || !licenseChecker->hasValidLicense()) { + qWarning() << "Invalid license, disabling Qt Creator Enterprise Auto Test Add-on."; + return false; + } else if (!licenseChecker->enterpriseFeatures()) + return false; + return true; +} + bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorString) { // Register objects in the plugin manager's object pool @@ -82,13 +95,7 @@ bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorStri Q_UNUSED(arguments) Q_UNUSED(errorString) - LicenseChecker::LicenseCheckerPlugin *licenseChecker - = ExtensionSystem::PluginManager::getObject(); - - if (!licenseChecker || !licenseChecker->hasValidLicense()) { - qWarning() << "Invalid license, disabling Qt Creator Enterprise Auto Test Add-on."; - return true; - } else if (!licenseChecker->enterpriseFeatures()) + if (!checkLicense()) return true; QAction *action = new QAction(tr("Autotest action"), this); diff --git a/plugins/autotest/autotestplugin.h b/plugins/autotest/autotestplugin.h index 6d5365ddeea..5f761264a2d 100644 --- a/plugins/autotest/autotestplugin.h +++ b/plugins/autotest/autotestplugin.h @@ -49,6 +49,7 @@ private slots: void triggerAction(); private: + bool checkLicense(); const QSharedPointer m_settings; }; From 1cc239ef41d1e7d356979d3dca59c3489b1dfba7 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Fri, 19 Dec 2014 11:25:05 +0100 Subject: [PATCH 033/200] move create menu entries to extra function Change-Id: Ia504e453b6cacc254ea598c629c3762c03cfa783 Reviewed-by: Christian Stenger --- plugins/autotest/autotestplugin.cpp | 25 +++++++++++++++---------- plugins/autotest/autotestplugin.h | 1 + 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index 7823fdef2c0..a4b3108cdd5 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -83,6 +83,20 @@ bool AutotestPlugin::checkLicense() return true; } +void AutotestPlugin::initializeMenuEntries() +{ + QAction *action = new QAction(tr("Autotest action"), this); + Core::Command *command = Core::ActionManager::registerAction(action, Constants::ACTION_ID, + Core::Context(Core::Constants::C_GLOBAL)); + command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Meta+A"))); + connect(action, SIGNAL(triggered()), this, SLOT(triggerAction())); + + Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::MENU_ID); + menu->menu()->setTitle(tr("Tests")); + menu->addAction(command); + Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu); +} + bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorString) { // Register objects in the plugin manager's object pool @@ -98,16 +112,7 @@ bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorStri if (!checkLicense()) return true; - QAction *action = new QAction(tr("Autotest action"), this); - Core::Command *cmd = Core::ActionManager::registerAction(action, Constants::ACTION_ID, - Core::Context(Core::Constants::C_GLOBAL)); - cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Meta+A"))); - connect(action, SIGNAL(triggered()), this, SLOT(triggerAction())); - - Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::MENU_ID); - menu->menu()->setTitle(tr("Tests")); - menu->addAction(cmd); - Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu); + initializeMenuEntries(); m_settings->fromSettings(Core::ICore::settings()); TestSettingsPage *settingsPage = new TestSettingsPage(m_settings); diff --git a/plugins/autotest/autotestplugin.h b/plugins/autotest/autotestplugin.h index 5f761264a2d..71f887791db 100644 --- a/plugins/autotest/autotestplugin.h +++ b/plugins/autotest/autotestplugin.h @@ -50,6 +50,7 @@ private slots: private: bool checkLicense(); + void initializeMenuEntries(); const QSharedPointer m_settings; }; From b655f70aba37facac064609eb06c2f563fb87aa8 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Tue, 6 Jan 2015 15:24:31 +0100 Subject: [PATCH 034/200] move settings getter to cpp Change-Id: Iec90cfcd74192f13d270180db91db95d41253bc5 Reviewed-by: Christian Stenger --- plugins/autotest/autotestplugin.cpp | 5 +++++ plugins/autotest/autotestplugin.h | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index a4b3108cdd5..66a0e9156b2 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -70,6 +70,11 @@ AutotestPlugin *AutotestPlugin::instance() return m_instance; } +QSharedPointer AutotestPlugin::settings() const +{ + return m_settings; +} + bool AutotestPlugin::checkLicense() { LicenseChecker::LicenseCheckerPlugin *licenseChecker diff --git a/plugins/autotest/autotestplugin.h b/plugins/autotest/autotestplugin.h index 71f887791db..be4a8037171 100644 --- a/plugins/autotest/autotestplugin.h +++ b/plugins/autotest/autotestplugin.h @@ -39,11 +39,12 @@ public: static AutotestPlugin *instance(); + QSharedPointer settings() const; + bool initialize(const QStringList &arguments, QString *errorString); void extensionsInitialized(); ShutdownFlag aboutToShutdown(); - QSharedPointer settings() const { return m_settings; } private slots: void triggerAction(); From 0c737c21ff2808a6615b2b433e3d5a9beeda58bb Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Thu, 18 Dec 2014 17:39:27 +0100 Subject: [PATCH 035/200] no need of an pointer for settingspage Change-Id: I55d69bac267f6f601682aeeca9eedcf944e8b55a Reviewed-by: Marco Bubke Reviewed-by: Christian Stenger --- plugins/autotest/autotestplugin.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index 66a0e9156b2..c202171e548 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -120,9 +120,7 @@ bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorStri initializeMenuEntries(); m_settings->fromSettings(Core::ICore::settings()); - TestSettingsPage *settingsPage = new TestSettingsPage(m_settings); - addAutoReleasedObject(settingsPage); - + addAutoReleasedObject(new TestSettingsPage(m_settings)); addAutoReleasedObject(new TestNavigationWidgetFactory); addAutoReleasedObject(TestResultsPane::instance()); From be4c06fdaf0a8292f0ee9719ca1b53bfbeee6388 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Fri, 19 Dec 2014 11:22:53 +0100 Subject: [PATCH 036/200] introduce FaultyTestResult class Change-Id: I5f20741492dbb3d553bea30a677965d46d6d8eb3 Reviewed-by: Marco Bubke Reviewed-by: Christian Stenger --- plugins/autotest/testresult.cpp | 5 +++ plugins/autotest/testresult.h | 6 ++++ plugins/autotest/testrunner.cpp | 59 ++++++++++++++------------------- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp index 2ade2c42ae6..6c8d0639da5 100644 --- a/plugins/autotest/testresult.cpp +++ b/plugins/autotest/testresult.cpp @@ -21,6 +21,11 @@ namespace Autotest { namespace Internal { +FaultyTestResult::FaultyTestResult(ResultType result, const QString &description) + : TestResult(QString(), QString(), QString(), result, description) +{ +} + TestResult::TestResult(const QString &className, const QString &testCase, const QString &dataTag, ResultType result, const QString &description) : m_class(className), diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index 86d3517a9d6..dcdf4ee0a13 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -76,6 +76,12 @@ private: // environment? }; +class FaultyTestResult : public TestResult +{ +public: + FaultyTestResult(ResultType result, const QString &description); +}; + bool operator==(const TestResult &t1, const TestResult &t2); } // namespace Internal diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index f3f7e371439..96a89683630 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -289,13 +289,11 @@ void processOutput() description.append(line); } } else if (xmlStartsWith(line, QLatin1String(""), qtVersion)) { - TestResultsPane::instance()->addTestResult( - TestResult(QString(), QString(), QString(), ResultType::MESSAGE_INTERNAL, - QObject::tr("Qt Version: %1").arg(qtVersion))); + TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_INTERNAL, + QObject::tr("Qt Version: %1").arg(qtVersion))); } else if (xmlStartsWith(line, QLatin1String(""), qtestVersion)) { - TestResultsPane::instance()->addTestResult( - TestResult(QString(), QString(), QString(), ResultType::MESSAGE_INTERNAL, - QObject::tr("QTest Version: %1").arg(qtestVersion))); + TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_INTERNAL, + QObject::tr("QTest Version: %1").arg(qtestVersion))); } else { // qDebug() << "Unhandled line:" << line; // TODO remove } @@ -346,9 +344,8 @@ bool performExec(const QString &cmd, const QStringList &args, const QString &wor } if (runCmd.isEmpty()) { - TestResultsPane::instance()->addTestResult( - TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, - QObject::tr("*** Could not find command '%1' ***").arg(cmd))); + TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_FATAL, + QObject::tr("*** Could not find command '%1' ***").arg(cmd))); return false; } @@ -369,9 +366,8 @@ bool performExec(const QString &cmd, const QStringList &args, const QString &wor if (m_currentFuture->isCanceled()) { m_runner->kill(); m_runner->waitForFinished(); - TestResultsPane::instance()->addTestResult( - TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, - QObject::tr("*** Test Run canceled by user ***"))); + TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_FATAL, + QObject::tr("*** Test Run canceled by user ***"))); } qApp->processEvents(); } @@ -382,10 +378,8 @@ bool performExec(const QString &cmd, const QStringList &args, const QString &wor if (m_runner->state() != QProcess::NotRunning) { m_runner->kill(); m_runner->waitForFinished(); - TestResultsPane::instance()->addTestResult( - TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, - QObject::tr("*** Test Case canceled due to timeout ***\n" - "Maybe raise the timeout?"))); + TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_FATAL, + QObject::tr("*** Test Case canceled due to timeout ***\nMaybe raise the timeout?"))); } return false; } @@ -444,11 +438,10 @@ void TestRunner::runTests() foreach (TestConfiguration *config, m_selectedTests) if (!config->project()) { toBeRemoved.append(config); - TestResultsPane::instance()->addTestResult( - TestResult(QString(), QString(), QString(), ResultType::MESSAGE_WARN, - tr("*** Project is null for '%1' - removing from Test Run ***\n" - "This might be the case for a faulty environment or similar." - ).arg(config->displayName()))); + TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_WARN, + tr("*** Project is null for '%1' - removing from Test Run ***\n" + "This might be the case for a faulty environment or similar." + ).arg(config->displayName()))); } foreach (TestConfiguration *config, toBeRemoved) { m_selectedTests.removeOne(config); @@ -456,19 +449,17 @@ void TestRunner::runTests() } if (m_selectedTests.empty()) { - TestResultsPane::instance()->addTestResult( - TestResult(QString(), QString(), QString(), ResultType::MESSAGE_WARN, - tr("*** No tests selected - canceling Test Run ***"))); + TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_WARN, + tr("*** No tests selected - canceling Test Run ***"))); return; } ProjectExplorer::Project *project = m_selectedTests.at(0)->project(); if (!project) { - TestResultsPane::instance()->addTestResult( - TestResult(QString(), QString(), QString(), ResultType::MESSAGE_WARN, - tr("*** Project is null - canceling Test Run ***\n" - "Actually only Desktop kits are supported - make sure the " - "current active kit is a Desktop kit."))); + TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_WARN, + tr("*** Project is null - canceling Test Run ***\n" + "Actually only Desktop kits are supported - make sure the " + "current active kit is a Desktop kit."))); return; } @@ -476,9 +467,8 @@ void TestRunner::runTests() ProjectExplorer::Internal::ProjectExplorerSettings pes = pep->projectExplorerSettings(); if (pes.buildBeforeDeploy) { if (!project->hasActiveBuildSettings()) { - TestResultsPane::instance()->addTestResult( - TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, - tr("*** Project is not configured - canceling Test Run ***"))); + TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_FATAL, + tr("*** Project is not configured - canceling Test Run ***"))); return; } buildProject(project); @@ -487,9 +477,8 @@ void TestRunner::runTests() } if (!m_buildSucceeded) { - TestResultsPane::instance()->addTestResult( - TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL, - tr("*** Build failed - canceling Test Run ***"))); + TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_FATAL, + tr("*** Build failed - canceling Test Run ***"))); return; } } From ba8979d0660dbff201fac6ccc79d2741108608d1 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Thu, 8 Jan 2015 12:51:01 +0100 Subject: [PATCH 037/200] Get rid of the Locker in TestResultModel... ...use signals and slots instead. Additionally re-use the existing item that is displaying the "Entering Test Function..." information. Change-Id: Ibedac01ced9e987d542aa4dc878588fbec84d585 Reviewed-by: Tim Jenssen --- plugins/autotest/autotestplugin.cpp | 2 ++ plugins/autotest/testresult.h | 5 +++- plugins/autotest/testresultmodel.cpp | 28 +++------------------- plugins/autotest/testresultmodel.h | 2 -- plugins/autotest/testresultspane.h | 3 +-- plugins/autotest/testrunner.cpp | 36 ++++++++++++++++++---------- plugins/autotest/testrunner.h | 1 + 7 files changed, 35 insertions(+), 42 deletions(-) diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index c202171e548..624812200ce 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -51,6 +51,8 @@ static AutotestPlugin *m_instance = 0; AutotestPlugin::AutotestPlugin() : m_settings(new TestSettings) { + // needed to be used in QueuedConnection connects + qRegisterMetaType(); // Create your members m_instance = this; } diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index dcdf4ee0a13..1a9da57528f 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -46,7 +46,8 @@ class TestResult { public: - TestResult(const QString &className, const QString &testCase, const QString &dataTag = QString(), + TestResult(const QString &className = QString(), const QString &testCase = QString(), + const QString &dataTag = QString(), ResultType result = UNKNOWN, const QString &description = QString()); QString className() const { return m_class; } @@ -57,6 +58,7 @@ public: QString fileName() const { return m_file; } int line() const { return m_line; } + void setDescription(const QString &description) { m_description = description; } void setFileName(const QString &fileName) { m_file = fileName; } void setLine(int line) { m_line = line; } @@ -87,6 +89,7 @@ bool operator==(const TestResult &t1, const TestResult &t2); } // namespace Internal } // namespace Autotest +Q_DECLARE_METATYPE(Autotest::Internal::TestResult) Q_DECLARE_METATYPE(Autotest::Internal::ResultType) #endif // TESTRESULT_H diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index 6ccc3946ffd..1f96257596d 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -36,7 +36,6 @@ TestResultModel::TestResultModel(QObject *parent) : TestResultModel::~TestResultModel() { - QWriteLocker lock(&m_rwLock); m_testResults.clear(); } @@ -54,7 +53,6 @@ QModelIndex TestResultModel::parent(const QModelIndex &) const int TestResultModel::rowCount(const QModelIndex &parent) const { - QReadLocker lock(&m_rwLock); return parent.isValid() ? 0 : m_testResults.size(); } @@ -85,7 +83,6 @@ static QIcon testResultIcon(ResultType result) { QVariant TestResultModel::data(const QModelIndex &index, int role) const { - QReadLocker lock(&m_rwLock); if (!index.isValid() || index.row() >= m_testResults.count() || index.column() != 0) return QVariant(); if (role == Qt::DisplayRole) { @@ -118,23 +115,17 @@ void TestResultModel::addTestResult(const TestResult &testResult) const bool isCurrentTestMssg = testResult.result() == ResultType::MESSAGE_CURRENT_TEST; const bool hasCurrentTestMssg = m_availableResultTypes.contains(ResultType::MESSAGE_CURRENT_TEST); - QReadLocker rLock(&m_rwLock); int position = m_testResults.size(); - rLock.unlock(); if (hasCurrentTestMssg && isCurrentTestMssg) { - beginRemoveRows(QModelIndex(), position, position); - QWriteLocker wLock(&m_rwLock); - m_testResults.replace(position - 1, testResult); - wLock.unlock(); - endRemoveRows(); + m_testResults.last().setDescription(testResult.description()); + const QModelIndex changed = index(m_testResults.size() - 1, 0, QModelIndex()); + emit dataChanged(changed, changed); } else { if (!isCurrentTestMssg && position) // decrement only if at least one other item --position; beginInsertRows(QModelIndex(), position, position); - QWriteLocker wLock(&m_rwLock); m_testResults.insert(position, testResult); - wLock.unlock(); endInsertRows(); } @@ -148,13 +139,9 @@ void TestResultModel::addTestResult(const TestResult &testResult) void TestResultModel::removeCurrentTestMessage() { - QReadLocker rLock(&m_rwLock); if (m_availableResultTypes.contains(ResultType::MESSAGE_CURRENT_TEST)) { beginRemoveRows(QModelIndex(), m_testResults.size() - 1, m_testResults.size() - 1); - rLock.unlock(); - QWriteLocker wLock(&m_rwLock); m_testResults.removeLast(); - wLock.unlock(); endRemoveRows(); m_availableResultTypes.remove(ResultType::MESSAGE_CURRENT_TEST); } @@ -162,14 +149,10 @@ void TestResultModel::removeCurrentTestMessage() void TestResultModel::clearTestResults() { - QReadLocker rLock(&m_rwLock); if (m_testResults.size() == 0) return; beginRemoveRows(QModelIndex(), 0, m_testResults.size() - 1); - rLock.unlock(); - QWriteLocker wLock(&m_rwLock); m_testResults.clear(); - wLock.unlock(); m_testResultCount.clear(); m_lastMaxWidthIndex = 0; m_maxWidthOfFileName = 0; @@ -182,15 +165,12 @@ TestResult TestResultModel::testResult(const QModelIndex &index) const { if (!index.isValid()) return TestResult(QString(), QString()); - QReadLocker lock(&m_rwLock); return m_testResults.at(index.row()); } int TestResultModel::maxWidthOfFileName(const QFont &font) { - QReadLocker lock(&m_rwLock); int count = m_testResults.size(); - lock.unlock(); if (count == 0) return 0; if (m_maxWidthOfFileName > 0 && font == m_measurementFont && m_lastMaxWidthIndex == count - 1) @@ -200,9 +180,7 @@ int TestResultModel::maxWidthOfFileName(const QFont &font) m_measurementFont = font; for (int i = m_lastMaxWidthIndex; i < count; ++i) { - lock.relock(); QString filename = m_testResults.at(i).fileName(); - lock.unlock(); const int pos = filename.lastIndexOf(QLatin1Char('/')); if (pos != -1) filename = filename.mid(pos +1); diff --git a/plugins/autotest/testresultmodel.h b/plugins/autotest/testresultmodel.h index 7494161bb7a..9485e25649d 100644 --- a/plugins/autotest/testresultmodel.h +++ b/plugins/autotest/testresultmodel.h @@ -24,7 +24,6 @@ #include #include #include -#include #include namespace Autotest { @@ -67,7 +66,6 @@ private: int m_lastMaxWidthIndex; QFont m_measurementFont; QSet m_availableResultTypes; - mutable QReadWriteLock m_rwLock; }; class TestResultFilterModel : public QSortFilterProxyModel diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h index 338eca79014..99c35552362 100644 --- a/plugins/autotest/testresultspane.h +++ b/plugins/autotest/testresultspane.h @@ -52,8 +52,6 @@ public: virtual ~TestResultsPane(); static TestResultsPane *instance(); - void addTestResult(const TestResult &result); - // IOutputPane interface QWidget *outputWidget(QWidget *parent); QList toolBarWidgets() const; @@ -73,6 +71,7 @@ public: signals: public slots: + void addTestResult(const TestResult &result); private slots: void onItemActivated(const QModelIndex &index); diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 96a89683630..fc5646f3311 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -192,6 +192,11 @@ static bool xmlExtractBenchmarkInformation(const QString &code, const QString &t return false; } +void emitTestResultCreated(const TestResult &testResult) +{ + emit m_instance->testResultCreated(testResult); +} + /****************** XML line parser helper end ******************/ void processOutput() @@ -228,8 +233,8 @@ void processOutput() result = ResultType::UNKNOWN; lineNumber = 0; readingDescription = false; - TestResultsPane::instance()->addTestResult( - TestResult(className, testCase, QString(), ResultType::MESSAGE_CURRENT_TEST, + emitTestResultCreated( + TestResult(QString(), QString(), QString(), ResultType::MESSAGE_CURRENT_TEST, QObject::tr("Entering Test Function %1::%2") .arg(className).arg(testCase))); continue; @@ -253,13 +258,13 @@ void processOutput() file = QFileInfo(m_runner->workingDirectory(), file).canonicalFilePath(); testResult.setFileName(file); testResult.setLine(lineNumber); - TestResultsPane::instance()->addTestResult(testResult); + emitTestResultCreated(testResult); } continue; } if (xmlExtractBenchmarkInformation(line, QLatin1String("addTestResult(testResult); + emitTestResultCreated(testResult); continue; } if (line == QLatin1String("") || line == QLatin1String("")) { @@ -268,17 +273,17 @@ void processOutput() file = QFileInfo(m_runner->workingDirectory(), file).canonicalFilePath(); testResult.setFileName(file); testResult.setLine(lineNumber); - TestResultsPane::instance()->addTestResult(testResult); + emitTestResultCreated(testResult); description = QString(); } else if (line == QLatin1String("") && !duration.isEmpty()) { TestResult testResult(className, testCase, QString(), ResultType::MESSAGE_INTERNAL, QObject::tr("execution took %1ms").arg(duration)); - TestResultsPane::instance()->addTestResult(testResult); + emitTestResultCreated(testResult); m_currentFuture->setProgressValue(m_currentFuture->progressValue() + 1); } else if (line == QLatin1String("") && !duration.isEmpty()) { TestResult testResult(className, QString(), QString(), ResultType::MESSAGE_INTERNAL, QObject::tr("Test execution took %1ms").arg(duration)); - TestResultsPane::instance()->addTestResult(testResult); + emitTestResultCreated(testResult); } else if (readingDescription) { if (line.endsWith(QLatin1String("]]>"))) { description.append(QLatin1Char('\n')); @@ -289,10 +294,10 @@ void processOutput() description.append(line); } } else if (xmlStartsWith(line, QLatin1String(""), qtVersion)) { - TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_INTERNAL, + emitTestResultCreated(FaultyTestResult(ResultType::MESSAGE_INTERNAL, QObject::tr("Qt Version: %1").arg(qtVersion))); } else if (xmlStartsWith(line, QLatin1String(""), qtestVersion)) { - TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_INTERNAL, + emitTestResultCreated(FaultyTestResult(ResultType::MESSAGE_INTERNAL, QObject::tr("QTest Version: %1").arg(qtestVersion))); } else { // qDebug() << "Unhandled line:" << line; // TODO remove @@ -344,7 +349,7 @@ bool performExec(const QString &cmd, const QStringList &args, const QString &wor } if (runCmd.isEmpty()) { - TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_FATAL, + emitTestResultCreated(FaultyTestResult(ResultType::MESSAGE_FATAL, QObject::tr("*** Could not find command '%1' ***").arg(cmd))); return false; } @@ -366,7 +371,7 @@ bool performExec(const QString &cmd, const QStringList &args, const QString &wor if (m_currentFuture->isCanceled()) { m_runner->kill(); m_runner->waitForFinished(); - TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_FATAL, + emitTestResultCreated(FaultyTestResult(ResultType::MESSAGE_FATAL, QObject::tr("*** Test Run canceled by user ***"))); } qApp->processEvents(); @@ -378,7 +383,7 @@ bool performExec(const QString &cmd, const QStringList &args, const QString &wor if (m_runner->state() != QProcess::NotRunning) { m_runner->kill(); m_runner->waitForFinished(); - TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_FATAL, + emitTestResultCreated(FaultyTestResult(ResultType::MESSAGE_FATAL, QObject::tr("*** Test Case canceled due to timeout ***\nMaybe raise the timeout?"))); } return false; @@ -484,6 +489,10 @@ void TestRunner::runTests() } m_executingTests = true; + connect(this, &TestRunner::testResultCreated, + TestResultsPane::instance(), &TestResultsPane::addTestResult, + Qt::QueuedConnection); + emit testRunStarted(); QFuture future = QtConcurrent::run(&performTestRun , m_selectedTests); Core::FutureProgress *progress = Core::ProgressManager::addTask(future, tr("Running Tests"), @@ -516,6 +525,9 @@ void TestRunner::buildFinished(bool success) void TestRunner::onFinished() { + disconnect(this, &TestRunner::testResultCreated, + TestResultsPane::instance(), &TestResultsPane::addTestResult); + m_executingTests = false; emit testRunFinished(); } diff --git a/plugins/autotest/testrunner.h b/plugins/autotest/testrunner.h index 6b739b15941..53d0470c08a 100644 --- a/plugins/autotest/testrunner.h +++ b/plugins/autotest/testrunner.h @@ -46,6 +46,7 @@ public: signals: void testRunStarted(); void testRunFinished(); + void testResultCreated(const TestResult &testResult); public slots: void runTests(); From 35939ac40275621240bb4d708802a934b3bd4c65 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 7 Jan 2015 09:33:57 +0100 Subject: [PATCH 038/200] Avoid executing unnamed Quick Tests if no related main is executed anyway Change-Id: I521065577c195713bc252e6762a88011996f045c Reviewed-by: Tim Jenssen --- plugins/autotest/testconfiguration.cpp | 6 ++++++ plugins/autotest/testconfiguration.h | 3 +++ plugins/autotest/testtreemodel.cpp | 5 ++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/plugins/autotest/testconfiguration.cpp b/plugins/autotest/testconfiguration.cpp index 73cdbdb918e..9589d68c027 100644 --- a/plugins/autotest/testconfiguration.cpp +++ b/plugins/autotest/testconfiguration.cpp @@ -29,6 +29,7 @@ TestConfiguration::TestConfiguration(const QString &testClass, const QStringList m_testClass(testClass), m_testCases(testCases), m_testCaseCount(testCaseCount), + m_unnamedOnly(false), m_project(0) { if (testCases.size() != 0) { @@ -96,5 +97,10 @@ void TestConfiguration::setProject(ProjectExplorer::Project *project) m_project = project; } +void TestConfiguration::setUnnamedOnly(bool unnamedOnly) +{ + m_unnamedOnly = unnamedOnly; +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testconfiguration.h b/plugins/autotest/testconfiguration.h index 54be3697aa0..8d9235b512b 100644 --- a/plugins/autotest/testconfiguration.h +++ b/plugins/autotest/testconfiguration.h @@ -49,6 +49,7 @@ public: void setDisplayName(const QString &displayName); void setEnvironment(const Utils::Environment &env); void setProject(ProjectExplorer::Project *project); + void setUnnamedOnly(bool unnamedOnly); QString testClass() const { return m_testClass; } QStringList testCases() const { return m_testCases; } @@ -60,6 +61,7 @@ public: QString displayName() const { return m_displayName; } Utils::Environment environment() const { return m_environment; } ProjectExplorer::Project *project() const { return m_project; } + bool unnamedOnly() const { return m_unnamedOnly; } signals: @@ -70,6 +72,7 @@ private: QString m_testClass; QStringList m_testCases; int m_testCaseCount; + bool m_unnamedOnly; QString m_proFile; QString m_targetFile; QString m_targetName; diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 8425c27c1db..7060203a418 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -465,6 +465,7 @@ QList TestTreeModel::getSelectedTests() const } else { TestConfiguration *tc = new TestConfiguration(QString(), QStringList()); tc->setTestCaseCount(1); + tc->setUnnamedOnly(true); addProjectInformation(tc, mainFile); foundMains.insert(mainFile, tc); } @@ -499,6 +500,7 @@ QList TestTreeModel::getSelectedTests() const // unnamed test case if (oldFunctions.size() == 0) { tc->setTestCaseCount(tc->testCaseCount() + testFunctions.size()); + tc->setUnnamedOnly(false); } else { oldFunctions << testFunctions; tc->setTestCases(oldFunctions); @@ -513,7 +515,8 @@ QList TestTreeModel::getSelectedTests() const } foreach (TestConfiguration *config, foundMains.values()) - result << config; + if (!config->unnamedOnly()) + result << config; return result; } From 96205e28fe901abb714c1e9a05a02d0131f578cb Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Thu, 8 Jan 2015 12:52:17 +0100 Subject: [PATCH 039/200] fix warning that "pep" is initialized but not referenced Change-Id: I1f12323e1de481f800fcf835a12213059b72bfd4 Reviewed-by: Christian Stenger --- plugins/autotest/testrunner.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index fc5646f3311..e687b03fe7e 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -468,8 +468,8 @@ void TestRunner::runTests() return; } - ProjectExplorer::ProjectExplorerPlugin *pep = ProjectExplorer::ProjectExplorerPlugin::instance(); - ProjectExplorer::Internal::ProjectExplorerSettings pes = pep->projectExplorerSettings(); + ProjectExplorer::Internal::ProjectExplorerSettings pes = + ProjectExplorer::ProjectExplorerPlugin::projectExplorerSettings(); if (pes.buildBeforeDeploy) { if (!project->hasActiveBuildSettings()) { TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_FATAL, @@ -507,10 +507,9 @@ void TestRunner::buildProject(ProjectExplorer::Project *project) m_buildSucceeded = false; ProjectExplorer::BuildManager *mgr = static_cast( ProjectExplorer::BuildManager::instance()); - ProjectExplorer::ProjectExplorerPlugin *pep = ProjectExplorer::ProjectExplorerPlugin::instance(); connect(mgr, &ProjectExplorer::BuildManager::buildQueueFinished, this, &TestRunner::buildFinished); - pep->buildProject(project); + ProjectExplorer::ProjectExplorerPlugin::buildProject(project); } void TestRunner::buildFinished(bool success) From e0616dc889e9e70395d3ada9347406c877f8ad16 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Thu, 8 Jan 2015 12:57:07 +0100 Subject: [PATCH 040/200] use variable instead of anonymous "false" Change-Id: I4ca2f7d82e70306ffae50d5eea31357e9fcfd0aa Reviewed-by: Christian Stenger --- plugins/autotest/testcodeparser.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index e2d342cb486..46cc75ad4bf 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -249,8 +249,10 @@ static QList scanDirectoryForQuickTestQmlFiles(const QStri QFutureInterface future; QmlJS::PathsAndLanguages paths; paths.maybeInsert(Utils::FileName::fromString(srcDir), QmlJS::Dialect::Qml); - QmlJS::ModelManagerInterface::importScan(future, qmlJsMM->workingCopy(), - paths, qmlJsMM, false, false); + const bool dontEmitDocumentChanges = false; + const bool notOnlyTheLib = false; + QmlJS::ModelManagerInterface::importScan(future, qmlJsMM->workingCopy(), paths, qmlJsMM, + dontEmitDocumentChanges, notOnlyTheLib); const QmlJS::Snapshot snapshot = QmlJSTools::Internal::ModelManager::instance()->snapshot(); QDirIterator it(srcDir, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); From 0c9531f384ab83d4be243742a3f9325ebf8f1d7e Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Thu, 8 Jan 2015 13:46:28 +0100 Subject: [PATCH 041/200] don't pollute the Autotest namespace with an enum Change-Id: Ic6c3e3beaba15e83c8524394ccc6a1953e76d59a Reviewed-by: Christian Stenger --- plugins/autotest/testresult.cpp | 138 ++++++++++++------------ plugins/autotest/testresult.h | 22 ++-- plugins/autotest/testresultdelegate.cpp | 30 +++--- plugins/autotest/testresultmodel.cpp | 44 ++++---- plugins/autotest/testresultmodel.h | 12 +-- plugins/autotest/testresultspane.cpp | 40 +++---- plugins/autotest/testrunner.cpp | 34 +++--- 7 files changed, 161 insertions(+), 159 deletions(-) diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp index 6c8d0639da5..810dcf2c43e 100644 --- a/plugins/autotest/testresult.cpp +++ b/plugins/autotest/testresult.cpp @@ -21,13 +21,13 @@ namespace Autotest { namespace Internal { -FaultyTestResult::FaultyTestResult(ResultType result, const QString &description) +FaultyTestResult::FaultyTestResult(Result::Type result, const QString &description) : TestResult(QString(), QString(), QString(), result, description) { } TestResult::TestResult(const QString &className, const QString &testCase, const QString &dataTag, - ResultType result, const QString &description) + Result::Type result, const QString &description) : m_class(className), m_case(testCase), m_dataTag(dataTag), @@ -37,125 +37,125 @@ TestResult::TestResult(const QString &className, const QString &testCase, const { } -ResultType TestResult::resultFromString(const QString &resultString) +Result::Type TestResult::resultFromString(const QString &resultString) { if (resultString == QLatin1String("pass")) - return PASS; + return Result::PASS; if (resultString == QLatin1String("fail")) - return FAIL; + return Result::FAIL; if (resultString == QLatin1String("xfail")) - return EXPECTED_FAIL; + return Result::EXPECTED_FAIL; if (resultString == QLatin1String("xpass")) - return UNEXPECTED_PASS; + return Result::UNEXPECTED_PASS; if (resultString == QLatin1String("skip")) - return SKIP; + return Result::SKIP; if (resultString == QLatin1String("qdebug")) - return MESSAGE_DEBUG; + return Result::MESSAGE_DEBUG; if (resultString == QLatin1String("warn") || resultString == QLatin1String("qwarn")) - return MESSAGE_WARN; + return Result::MESSAGE_WARN; if (resultString == QLatin1String("qfatal")) - return MESSAGE_FATAL; + return Result::MESSAGE_FATAL; if (resultString == QLatin1String("bpass")) - return BLACKLISTED_PASS; + return Result::BLACKLISTED_PASS; if (resultString == QLatin1String("bfail")) - return BLACKLISTED_FAIL; + return Result::BLACKLISTED_FAIL; qDebug(" unexpected testresult..."); qDebug(resultString.toLatin1()); - return UNKNOWN; + return Result::UNKNOWN; } -ResultType TestResult::toResultType(int rt) +Result::Type TestResult::toResultType(int rt) { switch(rt) { - case PASS: - return PASS; - case FAIL: - return FAIL; - case EXPECTED_FAIL: - return EXPECTED_FAIL; - case UNEXPECTED_PASS: - return UNEXPECTED_PASS; - case SKIP: - return SKIP; - case BLACKLISTED_PASS: - return BLACKLISTED_PASS; - case BLACKLISTED_FAIL: - return BLACKLISTED_FAIL; - case BENCHMARK: - return BENCHMARK; - case MESSAGE_DEBUG: - return MESSAGE_DEBUG; - case MESSAGE_WARN: - return MESSAGE_WARN; - case MESSAGE_FATAL: - return MESSAGE_FATAL; - case MESSAGE_INTERNAL: - return MESSAGE_INTERNAL; - case MESSAGE_CURRENT_TEST: - return MESSAGE_CURRENT_TEST; + case Result::PASS: + return Result::PASS; + case Result::FAIL: + return Result::FAIL; + case Result::EXPECTED_FAIL: + return Result::EXPECTED_FAIL; + case Result::UNEXPECTED_PASS: + return Result::UNEXPECTED_PASS; + case Result::SKIP: + return Result::SKIP; + case Result::BLACKLISTED_PASS: + return Result::BLACKLISTED_PASS; + case Result::BLACKLISTED_FAIL: + return Result::BLACKLISTED_FAIL; + case Result::BENCHMARK: + return Result::BENCHMARK; + case Result::MESSAGE_DEBUG: + return Result::MESSAGE_DEBUG; + case Result::MESSAGE_WARN: + return Result::MESSAGE_WARN; + case Result::MESSAGE_FATAL: + return Result::MESSAGE_FATAL; + case Result::MESSAGE_INTERNAL: + return Result::MESSAGE_INTERNAL; + case Result::MESSAGE_CURRENT_TEST: + return Result::MESSAGE_CURRENT_TEST; default: - return UNKNOWN; + return Result::UNKNOWN; } } -QString TestResult::resultToString(const ResultType type) +QString TestResult::resultToString(const Result::Type type) { switch(type) { - case PASS: + case Result::PASS: return QLatin1String("PASS"); - case FAIL: + case Result::FAIL: return QLatin1String("FAIL"); - case EXPECTED_FAIL: + case Result::EXPECTED_FAIL: return QLatin1String("XFAIL"); - case UNEXPECTED_PASS: + case Result::UNEXPECTED_PASS: return QLatin1String("XPASS"); - case SKIP: + case Result::SKIP: return QLatin1String("SKIP"); - case BENCHMARK: + case Result::BENCHMARK: return QLatin1String("BENCH"); - case MESSAGE_DEBUG: + case Result::MESSAGE_DEBUG: return QLatin1String("DEBUG"); - case MESSAGE_WARN: + case Result::MESSAGE_WARN: return QLatin1String("WARN"); - case MESSAGE_FATAL: + case Result::MESSAGE_FATAL: return QLatin1String("FATAL"); - case MESSAGE_INTERNAL: - case MESSAGE_CURRENT_TEST: + case Result::MESSAGE_INTERNAL: + case Result::MESSAGE_CURRENT_TEST: return QString(); - case BLACKLISTED_PASS: + case Result::BLACKLISTED_PASS: return QLatin1String("BPASS"); - case BLACKLISTED_FAIL: + case Result::BLACKLISTED_FAIL: return QLatin1String("BFAIL"); default: return QLatin1String("UNKNOWN"); } } -QColor TestResult::colorForType(const ResultType type) +QColor TestResult::colorForType(const Result::Type type) { switch(type) { - case PASS: + case Result::PASS: return QColor("#009900"); - case FAIL: + case Result::FAIL: return QColor("#a00000"); - case EXPECTED_FAIL: + case Result::EXPECTED_FAIL: return QColor("#00ff00"); - case UNEXPECTED_PASS: + case Result::UNEXPECTED_PASS: return QColor("#ff0000"); - case SKIP: + case Result::SKIP: return QColor("#787878"); - case BLACKLISTED_PASS: + case Result::BLACKLISTED_PASS: return QColor(0, 0, 0); - case BLACKLISTED_FAIL: + case Result::BLACKLISTED_FAIL: return QColor(0, 0, 0); - case MESSAGE_DEBUG: + case Result::MESSAGE_DEBUG: return QColor("#329696"); - case MESSAGE_WARN: + case Result::MESSAGE_WARN: return QColor("#d0bb00"); - case MESSAGE_FATAL: + case Result::MESSAGE_FATAL: return QColor("#640000"); - case MESSAGE_INTERNAL: - case MESSAGE_CURRENT_TEST: + case Result::MESSAGE_INTERNAL: + case Result::MESSAGE_CURRENT_TEST: return QColor("transparent"); default: return QColor("#000000"); diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index 1a9da57528f..65b801d5d05 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -25,7 +25,8 @@ namespace Autotest { namespace Internal { -enum ResultType { +namespace Result{ +enum Type { PASS, FAIL, EXPECTED_FAIL, @@ -41,6 +42,7 @@ enum ResultType { MESSAGE_CURRENT_TEST, UNKNOWN // ??? }; +} class TestResult { @@ -48,12 +50,12 @@ public: TestResult(const QString &className = QString(), const QString &testCase = QString(), const QString &dataTag = QString(), - ResultType result = UNKNOWN, const QString &description = QString()); + Result::Type result = Result::UNKNOWN, const QString &description = QString()); QString className() const { return m_class; } QString testCase() const { return m_case; } QString dataTag() const { return m_dataTag; } - ResultType result() const { return m_result; } + Result::Type result() const { return m_result; } QString description() const { return m_description; } QString fileName() const { return m_file; } int line() const { return m_line; } @@ -62,16 +64,16 @@ public: void setFileName(const QString &fileName) { m_file = fileName; } void setLine(int line) { m_line = line; } - static ResultType resultFromString(const QString &resultString); - static ResultType toResultType(int rt); - static QString resultToString(const ResultType type); - static QColor colorForType(const ResultType type); + static Result::Type resultFromString(const QString &resultString); + static Result::Type toResultType(int rt); + static QString resultToString(const Result::Type type); + static QColor colorForType(const Result::Type type); private: QString m_class; QString m_case; QString m_dataTag; - ResultType m_result; + Result::Type m_result; QString m_description; QString m_file; int m_line; @@ -81,7 +83,7 @@ private: class FaultyTestResult : public TestResult { public: - FaultyTestResult(ResultType result, const QString &description); + FaultyTestResult(Result::Type result, const QString &description); }; bool operator==(const TestResult &t1, const TestResult &t2); @@ -90,6 +92,6 @@ bool operator==(const TestResult &t1, const TestResult &t2); } // namespace Autotest Q_DECLARE_METATYPE(Autotest::Internal::TestResult) -Q_DECLARE_METATYPE(Autotest::Internal::ResultType) +Q_DECLARE_METATYPE(Autotest::Internal::Result::Type) #endif // TESTRESULT_H diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp index 21a595fa6fc..e6df02dc9fb 100644 --- a/plugins/autotest/testresultdelegate.cpp +++ b/plugins/autotest/testresultdelegate.cpp @@ -68,7 +68,7 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op TestResultModel *resultModel = static_cast(resultFilterModel->sourceModel()); LayoutPositions positions(opt, resultModel); TestResult testResult = resultModel->testResult(resultFilterModel->mapToSource(index)); - ResultType type = testResult.result(); + Result::Type type = testResult.result(); QIcon icon = index.data(Qt::DecorationRole).value(); if (!icon.isNull()) @@ -88,12 +88,12 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op const QString desc = testResult.description(); QString output; switch (type) { - case ResultType::PASS: - case ResultType::FAIL: - case ResultType::EXPECTED_FAIL: - case ResultType::UNEXPECTED_PASS: - case ResultType::BLACKLISTED_FAIL: - case ResultType::BLACKLISTED_PASS: + case Result::PASS: + case Result::FAIL: + case Result::EXPECTED_FAIL: + case Result::UNEXPECTED_PASS: + case Result::BLACKLISTED_FAIL: + case Result::BLACKLISTED_PASS: output = testResult.className() + QLatin1String("::") + testResult.testCase(); if (!testResult.dataTag().isEmpty()) output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); @@ -101,7 +101,7 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op output.append(QLatin1Char('\n')).append(desc); } break; - case ResultType::BENCHMARK: + case Result::BENCHMARK: output = testResult.className() + QLatin1String("::") + testResult.testCase(); if (!testResult.dataTag().isEmpty()) output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); @@ -202,12 +202,12 @@ QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo QString desc = testResult.description(); QString output; switch (testResult.result()) { - case ResultType::PASS: - case ResultType::FAIL: - case ResultType::EXPECTED_FAIL: - case ResultType::UNEXPECTED_PASS: - case ResultType::BLACKLISTED_FAIL: - case ResultType::BLACKLISTED_PASS: + case Result::PASS: + case Result::FAIL: + case Result::EXPECTED_FAIL: + case Result::UNEXPECTED_PASS: + case Result::BLACKLISTED_FAIL: + case Result::BLACKLISTED_PASS: output = testResult.className() + QLatin1String("::") + testResult.testCase(); if (!testResult.dataTag().isEmpty()) output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); @@ -215,7 +215,7 @@ QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo output.append(QLatin1Char('\n')).append(desc); } break; - case ResultType::BENCHMARK: + case Result::BENCHMARK: output = testResult.className() + QLatin1String("::") + testResult.testCase(); if (!testResult.dataTag().isEmpty()) output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index 1f96257596d..f0324458c38 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -61,7 +61,7 @@ int TestResultModel::columnCount(const QModelIndex &parent) const return parent.isValid() ? 0 : 1; } -static QIcon testResultIcon(ResultType result) { +static QIcon testResultIcon(Result::Type result) { static QIcon icons[11] = { QIcon(QLatin1String(":/images/pass.png")), QIcon(QLatin1String(":/images/fail.png")), @@ -76,7 +76,7 @@ static QIcon testResultIcon(ResultType result) { QIcon(QLatin1String(":/images/fatal.png")), }; // provide an icon for unknown?? - if (result < 0 || result >= MESSAGE_INTERNAL) + if (result < 0 || result >= Result::MESSAGE_INTERNAL) return QIcon(); return icons[result]; } @@ -88,14 +88,14 @@ QVariant TestResultModel::data(const QModelIndex &index, int role) const if (role == Qt::DisplayRole) { const TestResult &tr = m_testResults.at(index.row()); switch (tr.result()) { - case ResultType::PASS: - case ResultType::FAIL: - case ResultType::EXPECTED_FAIL: - case ResultType::UNEXPECTED_PASS: - case ResultType::SKIP: - case ResultType::BLACKLISTED_PASS: - case ResultType::BLACKLISTED_FAIL: - case ResultType::BENCHMARK: + case Result::PASS: + case Result::FAIL: + case Result::EXPECTED_FAIL: + case Result::UNEXPECTED_PASS: + case Result::SKIP: + case Result::BLACKLISTED_PASS: + case Result::BLACKLISTED_FAIL: + case Result::BENCHMARK: return QString::fromLatin1("%1::%2 (%3) - %4").arg(tr.className(), tr.testCase(), tr.dataTag(), tr.fileName()); default: @@ -112,8 +112,8 @@ QVariant TestResultModel::data(const QModelIndex &index, int role) const void TestResultModel::addTestResult(const TestResult &testResult) { - const bool isCurrentTestMssg = testResult.result() == ResultType::MESSAGE_CURRENT_TEST; - const bool hasCurrentTestMssg = m_availableResultTypes.contains(ResultType::MESSAGE_CURRENT_TEST); + const bool isCurrentTestMssg = testResult.result() == Result::MESSAGE_CURRENT_TEST; + const bool hasCurrentTestMssg = m_availableResultTypes.contains(Result::MESSAGE_CURRENT_TEST); int position = m_testResults.size(); @@ -139,11 +139,11 @@ void TestResultModel::addTestResult(const TestResult &testResult) void TestResultModel::removeCurrentTestMessage() { - if (m_availableResultTypes.contains(ResultType::MESSAGE_CURRENT_TEST)) { + if (m_availableResultTypes.contains(Result::MESSAGE_CURRENT_TEST)) { beginRemoveRows(QModelIndex(), m_testResults.size() - 1, m_testResults.size() - 1); m_testResults.removeLast(); endRemoveRows(); - m_availableResultTypes.remove(ResultType::MESSAGE_CURRENT_TEST); + m_availableResultTypes.remove(Result::MESSAGE_CURRENT_TEST); } } @@ -201,7 +201,7 @@ int TestResultModel::maxWidthOfLineNumber(const QFont &font) return m_widthOfLineNumber; } -int TestResultModel::resultTypeCount(ResultType type) +int TestResultModel::resultTypeCount(Result::Type type) { return m_testResultCount.value(type, 0); } @@ -218,16 +218,16 @@ TestResultFilterModel::TestResultFilterModel(TestResultModel *sourceModel, QObje void TestResultFilterModel::enableAllResultTypes() { - m_enabled << ResultType::PASS << ResultType::FAIL << ResultType::EXPECTED_FAIL - << ResultType::UNEXPECTED_PASS << ResultType::SKIP << ResultType::MESSAGE_DEBUG - << ResultType::MESSAGE_WARN << ResultType::MESSAGE_INTERNAL - << ResultType::MESSAGE_FATAL << ResultType::UNKNOWN << ResultType::BLACKLISTED_PASS - << ResultType::BLACKLISTED_FAIL << ResultType::BENCHMARK - << ResultType::MESSAGE_CURRENT_TEST; + m_enabled << Result::PASS << Result::FAIL << Result::EXPECTED_FAIL + << Result::UNEXPECTED_PASS << Result::SKIP << Result::MESSAGE_DEBUG + << Result::MESSAGE_WARN << Result::MESSAGE_INTERNAL + << Result::MESSAGE_FATAL << Result::UNKNOWN << Result::BLACKLISTED_PASS + << Result::BLACKLISTED_FAIL << Result::BENCHMARK + << Result::MESSAGE_CURRENT_TEST; invalidateFilter(); } -void TestResultFilterModel::toggleTestResultType(ResultType type) +void TestResultFilterModel::toggleTestResultType(Result::Type type) { if (m_enabled.contains(type)) { m_enabled.remove(type); diff --git a/plugins/autotest/testresultmodel.h b/plugins/autotest/testresultmodel.h index 9485e25649d..5747194a88b 100644 --- a/plugins/autotest/testresultmodel.h +++ b/plugins/autotest/testresultmodel.h @@ -51,8 +51,8 @@ public: int maxWidthOfFileName(const QFont &font); int maxWidthOfLineNumber(const QFont &font); - bool hasResultType(ResultType type) { return m_availableResultTypes.contains(type); } - int resultTypeCount(ResultType type); + bool hasResultType(Result::Type type) { return m_availableResultTypes.contains(type); } + int resultTypeCount(Result::Type type); signals: @@ -60,12 +60,12 @@ public slots: private: QList m_testResults; - QMap m_testResultCount; + QMap m_testResultCount; int m_widthOfLineNumber; int m_maxWidthOfFileName; int m_lastMaxWidthIndex; QFont m_measurementFont; - QSet m_availableResultTypes; + QSet m_availableResultTypes; }; class TestResultFilterModel : public QSortFilterProxyModel @@ -75,7 +75,7 @@ public: TestResultFilterModel(TestResultModel *sourceModel, QObject *parent = 0); void enableAllResultTypes(); - void toggleTestResultType(ResultType type); + void toggleTestResultType(Result::Type type); void clearTestResults(); bool hasResults(); TestResult testResult(const QModelIndex &index) const; @@ -85,7 +85,7 @@ protected: private: TestResultModel *m_sourceModel; - QSet m_enabled; + QSet m_enabled; }; } // namespace Internal diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 6d902705f1c..20c4fe2340d 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -276,23 +276,23 @@ void TestResultsPane::initializeFilterMenu() const bool omitIntern = AutotestPlugin::instance()->settings()->omitInternalMssg; // FilterModel has all messages enabled by default if (omitIntern) - m_filterModel->toggleTestResultType(ResultType::MESSAGE_INTERNAL); + m_filterModel->toggleTestResultType(Result::MESSAGE_INTERNAL); - QMap textAndType; - textAndType.insert(ResultType::PASS, tr("Pass")); - textAndType.insert(ResultType::FAIL, tr("Fail")); - textAndType.insert(ResultType::EXPECTED_FAIL, tr("Expected Fail")); - textAndType.insert(ResultType::UNEXPECTED_PASS, tr("Unexpected Pass")); - textAndType.insert(ResultType::SKIP, tr("Skip")); - textAndType.insert(ResultType::BENCHMARK, tr("Benchmarks")); - textAndType.insert(ResultType::MESSAGE_DEBUG, tr("Debug Messages")); - textAndType.insert(ResultType::MESSAGE_WARN, tr("Warning Messages")); - textAndType.insert(ResultType::MESSAGE_INTERNAL, tr("Internal Messages")); - foreach (ResultType result, textAndType.keys()) { + QMap textAndType; + textAndType.insert(Result::PASS, tr("Pass")); + textAndType.insert(Result::FAIL, tr("Fail")); + textAndType.insert(Result::EXPECTED_FAIL, tr("Expected Fail")); + textAndType.insert(Result::UNEXPECTED_PASS, tr("Unexpected Pass")); + textAndType.insert(Result::SKIP, tr("Skip")); + textAndType.insert(Result::BENCHMARK, tr("Benchmarks")); + textAndType.insert(Result::MESSAGE_DEBUG, tr("Debug Messages")); + textAndType.insert(Result::MESSAGE_WARN, tr("Warning Messages")); + textAndType.insert(Result::MESSAGE_INTERNAL, tr("Internal Messages")); + foreach (Result::Type result, textAndType.keys()) { QAction *action = new QAction(m_filterMenu); action->setText(textAndType.value(result)); action->setCheckable(true); - action->setChecked(result != ResultType::MESSAGE_INTERNAL || !omitIntern); + action->setChecked(result != Result::MESSAGE_INTERNAL || !omitIntern); action->setData(result); m_filterMenu->addAction(action); } @@ -307,22 +307,22 @@ void TestResultsPane::initializeFilterMenu() void TestResultsPane::updateSummaryLabel() { QString labelText = QString::fromLatin1("

Test Summary:   %1 %2, %3 %4") - .arg(QString::number(m_model->resultTypeCount(ResultType::PASS)), tr("passes"), - QString::number(m_model->resultTypeCount(ResultType::FAIL)), tr("fails")); - int count = m_model->resultTypeCount(ResultType::UNEXPECTED_PASS); + .arg(QString::number(m_model->resultTypeCount(Result::PASS)), tr("passes"), + QString::number(m_model->resultTypeCount(Result::FAIL)), tr("fails")); + int count = m_model->resultTypeCount(Result::UNEXPECTED_PASS); if (count) labelText.append(QString::fromLatin1(", %1 %2") .arg(QString::number(count), tr("unexpected passes"))); - count = m_model->resultTypeCount(ResultType::EXPECTED_FAIL); + count = m_model->resultTypeCount(Result::EXPECTED_FAIL); if (count) labelText.append(QString::fromLatin1(", %1 %2") .arg(QString::number(count), tr("expected fails"))); - count = m_model->resultTypeCount(ResultType::MESSAGE_FATAL); + count = m_model->resultTypeCount(Result::MESSAGE_FATAL); if (count) labelText.append(QString::fromLatin1(", %1 %2") .arg(QString::number(count), tr("fatals"))); - count = m_model->resultTypeCount(ResultType::BLACKLISTED_FAIL) - + m_model->resultTypeCount(ResultType::BLACKLISTED_PASS); + count = m_model->resultTypeCount(Result::BLACKLISTED_FAIL) + + m_model->resultTypeCount(Result::BLACKLISTED_PASS); if (count) labelText.append(QString::fromLatin1(", %1 %2") .arg(QString::number(count), tr("blacklisted"))); diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index e687b03fe7e..fb24280183d 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -99,7 +99,7 @@ static bool xmlCData(const QString &code, const QString &start, QString &result) } static bool xmlExtractTypeFileLine(const QString &code, const QString &tagStart, - ResultType &result, QString &file, int &line) + Result::Type &result, QString &file, int &line) { if (code.startsWith(tagStart)) { int start = code.indexOf(QLatin1String(" type=\"")) + 7; @@ -206,7 +206,7 @@ void processOutput() static QString className; static QString testCase; static QString dataTag; - static ResultType result = ResultType::UNKNOWN; + static Result::Type result = Result::UNKNOWN; static QString description; static QString file; static int lineNumber = 0; @@ -230,11 +230,11 @@ void processOutput() description = QString(); duration = QString(); file = QString(); - result = ResultType::UNKNOWN; + result = Result::UNKNOWN; lineNumber = 0; readingDescription = false; emitTestResultCreated( - TestResult(QString(), QString(), QString(), ResultType::MESSAGE_CURRENT_TEST, + TestResult(QString(), QString(), QString(), Result::MESSAGE_CURRENT_TEST, QObject::tr("Entering Test Function %1::%2") .arg(className).arg(testCase))); continue; @@ -263,7 +263,7 @@ void processOutput() continue; } if (xmlExtractBenchmarkInformation(line, QLatin1String("") && !duration.isEmpty()) { - TestResult testResult(className, testCase, QString(), ResultType::MESSAGE_INTERNAL, + TestResult testResult(className, testCase, QString(), Result::MESSAGE_INTERNAL, QObject::tr("execution took %1ms").arg(duration)); emitTestResultCreated(testResult); m_currentFuture->setProgressValue(m_currentFuture->progressValue() + 1); } else if (line == QLatin1String("") && !duration.isEmpty()) { - TestResult testResult(className, QString(), QString(), ResultType::MESSAGE_INTERNAL, + TestResult testResult(className, QString(), QString(), Result::MESSAGE_INTERNAL, QObject::tr("Test execution took %1ms").arg(duration)); emitTestResultCreated(testResult); } else if (readingDescription) { @@ -294,10 +294,10 @@ void processOutput() description.append(line); } } else if (xmlStartsWith(line, QLatin1String(""), qtVersion)) { - emitTestResultCreated(FaultyTestResult(ResultType::MESSAGE_INTERNAL, + emitTestResultCreated(FaultyTestResult(Result::MESSAGE_INTERNAL, QObject::tr("Qt Version: %1").arg(qtVersion))); } else if (xmlStartsWith(line, QLatin1String(""), qtestVersion)) { - emitTestResultCreated(FaultyTestResult(ResultType::MESSAGE_INTERNAL, + emitTestResultCreated(FaultyTestResult(Result::MESSAGE_INTERNAL, QObject::tr("QTest Version: %1").arg(qtestVersion))); } else { // qDebug() << "Unhandled line:" << line; // TODO remove @@ -349,7 +349,7 @@ bool performExec(const QString &cmd, const QStringList &args, const QString &wor } if (runCmd.isEmpty()) { - emitTestResultCreated(FaultyTestResult(ResultType::MESSAGE_FATAL, + emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, QObject::tr("*** Could not find command '%1' ***").arg(cmd))); return false; } @@ -371,7 +371,7 @@ bool performExec(const QString &cmd, const QStringList &args, const QString &wor if (m_currentFuture->isCanceled()) { m_runner->kill(); m_runner->waitForFinished(); - emitTestResultCreated(FaultyTestResult(ResultType::MESSAGE_FATAL, + emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, QObject::tr("*** Test Run canceled by user ***"))); } qApp->processEvents(); @@ -383,7 +383,7 @@ bool performExec(const QString &cmd, const QStringList &args, const QString &wor if (m_runner->state() != QProcess::NotRunning) { m_runner->kill(); m_runner->waitForFinished(); - emitTestResultCreated(FaultyTestResult(ResultType::MESSAGE_FATAL, + emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, QObject::tr("*** Test Case canceled due to timeout ***\nMaybe raise the timeout?"))); } return false; @@ -443,7 +443,7 @@ void TestRunner::runTests() foreach (TestConfiguration *config, m_selectedTests) if (!config->project()) { toBeRemoved.append(config); - TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_WARN, + TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, tr("*** Project is null for '%1' - removing from Test Run ***\n" "This might be the case for a faulty environment or similar." ).arg(config->displayName()))); @@ -454,14 +454,14 @@ void TestRunner::runTests() } if (m_selectedTests.empty()) { - TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_WARN, + TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, tr("*** No tests selected - canceling Test Run ***"))); return; } ProjectExplorer::Project *project = m_selectedTests.at(0)->project(); if (!project) { - TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_WARN, + TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, tr("*** Project is null - canceling Test Run ***\n" "Actually only Desktop kits are supported - make sure the " "current active kit is a Desktop kit."))); @@ -472,7 +472,7 @@ void TestRunner::runTests() ProjectExplorer::ProjectExplorerPlugin::projectExplorerSettings(); if (pes.buildBeforeDeploy) { if (!project->hasActiveBuildSettings()) { - TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_FATAL, + TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_FATAL, tr("*** Project is not configured - canceling Test Run ***"))); return; } @@ -482,7 +482,7 @@ void TestRunner::runTests() } if (!m_buildSucceeded) { - TestResultsPane::instance()->addTestResult(FaultyTestResult(ResultType::MESSAGE_FATAL, + TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_FATAL, tr("*** Build failed - canceling Test Run ***"))); return; } From 2287ba501fe30bc954d761a0afb2600d19f5dfae Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Thu, 8 Jan 2015 18:04:31 +0100 Subject: [PATCH 042/200] variables as complete words are better Change-Id: If433c621466f2e1160a016d2b7b2539e4dc8b3d6 Reviewed-by: Christian Stenger --- plugins/autotest/testrunner.cpp | 41 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index fb24280183d..ed7d4a0e5c6 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -336,30 +336,29 @@ static QString which(const QString &path, const QString &cmd) } return QString(); } - -bool performExec(const QString &cmd, const QStringList &args, const QString &workingDir, - const Utils::Environment &env, int timeout) +bool performExec(const QString &command, const QStringList &argumentList, const QString &workingDirectory, + const Utils::Environment &environment, int timeout) { QString runCmd; - if (!QDir::toNativeSeparators(cmd).contains(QDir::separator())) { - if (env.hasKey(QLatin1String("PATH"))) - runCmd = which(env.value(QLatin1String("PATH")), cmd); - } else if (QFileInfo(cmd).exists()) { - runCmd = cmd; + if (!QDir::toNativeSeparators(command).contains(QDir::separator())) { + if (environment.hasKey(QLatin1String("PATH"))) + runCmd = which(environment.value(QLatin1String("PATH")), command); + } else if (QFileInfo(command).exists()) { + runCmd = command; } if (runCmd.isEmpty()) { emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, - QObject::tr("*** Could not find command '%1' ***").arg(cmd))); + QObject::tr("*** Could not find command '%1' ***").arg(command))); return false; } - m_runner->setWorkingDirectory(workingDir); - m_runner->setProcessEnvironment(env.toProcessEnvironment()); + m_runner->setWorkingDirectory(workingDirectory); + m_runner->setProcessEnvironment(environment.toProcessEnvironment()); QTime executionTimer; - if (args.count()) { - m_runner->start(runCmd, args); + if (argumentList.count()) { + m_runner->start(runCmd, argumentList); } else { m_runner->start(runCmd); } @@ -413,18 +412,18 @@ void performTestRun(QFutureInterface &future, const QListtargetFile(); - QString workDir = tc->workingDirectory(); - QStringList args; - Utils::Environment env = tc->environment(); + QString command = tc->targetFile(); + QString workingDirectory = tc->workingDirectory(); + QStringList argumentList; + Utils::Environment environment = tc->environment(); - args << QLatin1String("-xml"); + argumentList << QLatin1String("-xml"); if (!metricsOption.isEmpty()) - args << metricsOption; + argumentList << metricsOption; if (tc->testCases().count()) - args << tc->testCases(); + argumentList << tc->testCases(); - performExec(cmd, args, workDir, env, timeout); + performExec(command, argumentList, workingDirectory, environment, timeout); } future.setProgressValue(testCaseCount); From 042b1d61d0153f61fad3da0199835c302e3243b4 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Tue, 13 Jan 2015 11:20:51 +0100 Subject: [PATCH 043/200] merge performTestRun and performExec This is a preparation for later refactoring. Also moved the get settings values outside from the threaded code. Change-Id: I0acceece4bc55a453880f4235e02a5712443b32d Reviewed-by: Christian Stenger --- plugins/autotest/testrunner.cpp | 111 +++++++++++++++----------------- 1 file changed, 52 insertions(+), 59 deletions(-) diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index ed7d4a0e5c6..607e02b6187 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -336,60 +336,8 @@ static QString which(const QString &path, const QString &cmd) } return QString(); } -bool performExec(const QString &command, const QStringList &argumentList, const QString &workingDirectory, - const Utils::Environment &environment, int timeout) -{ - QString runCmd; - if (!QDir::toNativeSeparators(command).contains(QDir::separator())) { - if (environment.hasKey(QLatin1String("PATH"))) - runCmd = which(environment.value(QLatin1String("PATH")), command); - } else if (QFileInfo(command).exists()) { - runCmd = command; - } - if (runCmd.isEmpty()) { - emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, - QObject::tr("*** Could not find command '%1' ***").arg(command))); - return false; - } - - m_runner->setWorkingDirectory(workingDirectory); - m_runner->setProcessEnvironment(environment.toProcessEnvironment()); - QTime executionTimer; - - if (argumentList.count()) { - m_runner->start(runCmd, argumentList); - } else { - m_runner->start(runCmd); - } - - bool ok = m_runner->waitForStarted(); - executionTimer.start(); - if (ok) { - while (m_runner->state() == QProcess::Running && executionTimer.elapsed() < timeout) { - if (m_currentFuture->isCanceled()) { - m_runner->kill(); - m_runner->waitForFinished(); - emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, - QObject::tr("*** Test Run canceled by user ***"))); - } - qApp->processEvents(); - } - } - if (ok && executionTimer.elapsed() < timeout) { - return m_runner->exitCode() == 0; - } else { - if (m_runner->state() != QProcess::NotRunning) { - m_runner->kill(); - m_runner->waitForFinished(); - emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, - QObject::tr("*** Test Case canceled due to timeout ***\nMaybe raise the timeout?"))); - } - return false; - } -} - -void performTestRun(QFutureInterface &future, const QList selectedTests) +void performTestRun(QFutureInterface &future, const QList selectedTests, const int timeout, const QString metricsOption) { int testCaseCount = 0; foreach (const TestConfiguration *config, selectedTests) @@ -405,10 +353,6 @@ void performTestRun(QFutureInterface &future, const QList settings = AutotestPlugin::instance()->settings(); - const int timeout = settings->timeout; - const QString metricsOption = TestSettings::metricsTypeToOption(settings->metrics); - foreach (const TestConfiguration *tc, selectedTests) { if (future.isCanceled()) break; @@ -422,8 +366,52 @@ void performTestRun(QFutureInterface &future, const QListtestCases().count()) argumentList << tc->testCases(); + QString runCmd; + if (!QDir::toNativeSeparators(command).contains(QDir::separator())) { + if (environment.hasKey(QLatin1String("PATH"))) + runCmd = which(environment.value(QLatin1String("PATH")), command); + } else if (QFileInfo(command).exists()) { + runCmd = command; + } - performExec(command, argumentList, workingDirectory, environment, timeout); + if (runCmd.isEmpty()) { + emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, + QObject::tr("*** Could not find command '%1' ***").arg(command))); + continue; + } + + m_runner->setWorkingDirectory(workingDirectory); + m_runner->setProcessEnvironment(environment.toProcessEnvironment()); + QTime executionTimer; + + if (argumentList.count()) { + m_runner->start(runCmd, argumentList); + } else { + m_runner->start(runCmd); + } + + bool ok = m_runner->waitForStarted(); + executionTimer.start(); + if (ok) { + while (m_runner->state() == QProcess::Running && executionTimer.elapsed() < timeout) { + if (m_currentFuture->isCanceled()) { + m_runner->kill(); + m_runner->waitForFinished(); + emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, + QObject::tr("*** Test Run canceled by user ***"))); + } + qApp->processEvents(); + } + } + + if (executionTimer.elapsed() >= timeout) { + if (m_runner->state() != QProcess::NotRunning) { + m_runner->kill(); + m_runner->waitForFinished(); + emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, QObject::tr( + "*** Test Case canceled due to timeout ***\nMaybe raise the timeout?"))); + } + } } future.setProgressValue(testCaseCount); @@ -492,8 +480,13 @@ void TestRunner::runTests() TestResultsPane::instance(), &TestResultsPane::addTestResult, Qt::QueuedConnection); + const QSharedPointer settings = AutotestPlugin::instance()->settings(); + const int timeout = settings->timeout; + const QString metricsOption = TestSettings::metricsTypeToOption(settings->metrics); + emit testRunStarted(); - QFuture future = QtConcurrent::run(&performTestRun , m_selectedTests); + + QFuture future = QtConcurrent::run(&performTestRun, m_selectedTests, timeout, metricsOption); Core::FutureProgress *progress = Core::ProgressManager::addTask(future, tr("Running Tests"), Autotest::Constants::TASK_INDEX); connect(progress, &Core::FutureProgress::finished, From 4297de7d4b097661a05235aa6a3277aea31972a4 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Tue, 13 Jan 2015 11:24:41 +0100 Subject: [PATCH 044/200] remove static variable testRunner Change-Id: I07dbde221632ec0aeca758f684c8ada2c71f3969 Reviewed-by: Christian Stenger --- plugins/autotest/testresultspane.cpp | 2 +- plugins/autotest/testrunner.cpp | 71 +++++++++++++--------------- plugins/autotest/testrunner.h | 2 +- 3 files changed, 35 insertions(+), 40 deletions(-) diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 20c4fe2340d..f2430fd420b 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -107,7 +107,7 @@ void TestResultsPane::createToolButtons() m_stopTestRun->setIcon(QIcon(QLatin1String(":/images/stop.png"))); m_stopTestRun->setToolTip(tr("Stop Test Run")); m_stopTestRun->setEnabled(false); - connect(m_stopTestRun, &QToolButton::clicked, TestRunner::instance(), &TestRunner::stopTestRun); + connect(m_stopTestRun, &QToolButton::clicked, TestRunner::instance(), &TestRunner::requestStopTestRun); m_filterButton = new QToolButton(m_listView); m_filterButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_FILTER))); diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 607e02b6187..3d2f37533c5 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -42,7 +42,6 @@ namespace Autotest { namespace Internal { static TestRunner *m_instance = 0; -static QProcess *m_runner = 0; static QFutureInterface *m_currentFuture = 0; TestRunner *TestRunner::instance() @@ -64,8 +63,6 @@ TestRunner::~TestRunner() qDeleteAll(m_selectedTests); m_selectedTests.clear(); m_instance = 0; - if (m_runner) - delete m_runner; } void TestRunner::setSelectedTests(const QList &selected) @@ -199,9 +196,9 @@ void emitTestResultCreated(const TestResult &testResult) /****************** XML line parser helper end ******************/ -void processOutput() +void processOutput(QProcess *testRunner) { - if (!m_runner) + if (!testRunner) return; static QString className; static QString testCase; @@ -216,9 +213,9 @@ void processOutput() static QString qtestVersion; static QString bmDescription; - while (m_runner->canReadLine()) { + while (testRunner->canReadLine()) { // TODO Qt5 uses UTF-8 - while Qt4 uses ISO-8859-1 - could this be a problem? - const QString line = QString::fromUtf8(m_runner->readLine()).trimmed(); + const QString line = QString::fromUtf8(testRunner->readLine()).trimmed(); if (line.isEmpty() || line.startsWith(QLatin1String(""))) { TestResult testResult(className, testCase, dataTag, result, description); if (!file.isEmpty()) - file = QFileInfo(m_runner->workingDirectory(), file).canonicalFilePath(); + file = QFileInfo(testRunner->workingDirectory(), file).canonicalFilePath(); testResult.setFileName(file); testResult.setLine(lineNumber); emitTestResultCreated(testResult); @@ -270,7 +267,7 @@ void processOutput() if (line == QLatin1String("") || line == QLatin1String("")) { TestResult testResult(className, testCase, dataTag, result, description); if (!file.isEmpty()) - file = QFileInfo(m_runner->workingDirectory(), file).canonicalFilePath(); + file = QFileInfo(testRunner->workingDirectory(), file).canonicalFilePath(); testResult.setFileName(file); testResult.setLine(lineNumber); emitTestResultCreated(testResult); @@ -337,24 +334,30 @@ static QString which(const QString &path, const QString &cmd) return QString(); } -void performTestRun(QFutureInterface &future, const QList selectedTests, const int timeout, const QString metricsOption) +void performTestRun(QFutureInterface &future, const QList selectedTests, const int timeout, const QString metricsOption, TestRunner* testRunner) { int testCaseCount = 0; foreach (const TestConfiguration *config, selectedTests) testCaseCount += config->testCaseCount(); m_currentFuture = &future; - m_runner = new QProcess; - m_runner->setReadChannelMode(QProcess::MergedChannels); - m_runner->setReadChannel(QProcess::StandardOutput); + QProcess testProcess; + testProcess.setReadChannelMode(QProcess::MergedChannels); + testProcess.setReadChannel(QProcess::StandardOutput); + QObject::connect(testRunner, &TestRunner::requestStopTestRun, [&] () { + if (testProcess.state() != QProcess::NotRunning && m_currentFuture) + m_currentFuture->cancel(); + }); - QObject::connect(m_runner, &QProcess::readyReadStandardOutput, &processOutput); + QObject::connect(&testProcess, &QProcess::readyReadStandardOutput, [&] () { + processOutput(&testProcess); + }); - future.setProgressRange(0, testCaseCount); - future.setProgressValue(0); + m_currentFuture->setProgressRange(0, testCaseCount); + m_currentFuture->setProgressValue(0); foreach (const TestConfiguration *tc, selectedTests) { - if (future.isCanceled()) + if (m_currentFuture->isCanceled()) break; QString command = tc->targetFile(); QString workingDirectory = tc->workingDirectory(); @@ -380,23 +383,23 @@ void performTestRun(QFutureInterface &future, const QListsetWorkingDirectory(workingDirectory); - m_runner->setProcessEnvironment(environment.toProcessEnvironment()); + testProcess.setWorkingDirectory(workingDirectory); + testProcess.setProcessEnvironment(environment.toProcessEnvironment()); QTime executionTimer; if (argumentList.count()) { - m_runner->start(runCmd, argumentList); + testProcess.start(runCmd, argumentList); } else { - m_runner->start(runCmd); + testProcess.start(runCmd); } - bool ok = m_runner->waitForStarted(); + bool ok = testProcess.waitForStarted(); executionTimer.start(); if (ok) { - while (m_runner->state() == QProcess::Running && executionTimer.elapsed() < timeout) { + while (testProcess.state() == QProcess::Running && executionTimer.elapsed() < timeout) { if (m_currentFuture->isCanceled()) { - m_runner->kill(); - m_runner->waitForFinished(); + testProcess.kill(); + testProcess.waitForFinished(); emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, QObject::tr("*** Test Run canceled by user ***"))); } @@ -405,18 +408,16 @@ void performTestRun(QFutureInterface &future, const QList= timeout) { - if (m_runner->state() != QProcess::NotRunning) { - m_runner->kill(); - m_runner->waitForFinished(); + if (testProcess.state() != QProcess::NotRunning) { + testProcess.kill(); + testProcess.waitForFinished(); emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, QObject::tr( "*** Test Case canceled due to timeout ***\nMaybe raise the timeout?"))); } } } - future.setProgressValue(testCaseCount); + m_currentFuture->setProgressValue(testCaseCount); - delete m_runner; - m_runner = 0; m_currentFuture = 0; } @@ -486,7 +487,7 @@ void TestRunner::runTests() emit testRunStarted(); - QFuture future = QtConcurrent::run(&performTestRun, m_selectedTests, timeout, metricsOption); + QFuture future = QtConcurrent::run(&performTestRun, m_selectedTests, timeout, metricsOption, this); Core::FutureProgress *progress = Core::ProgressManager::addTask(future, tr("Running Tests"), Autotest::Constants::TASK_INDEX); connect(progress, &Core::FutureProgress::finished, @@ -523,11 +524,5 @@ void TestRunner::onFinished() emit testRunFinished(); } -void TestRunner::stopTestRun() -{ - if (m_runner && m_runner->state() != QProcess::NotRunning && m_currentFuture) - m_currentFuture->cancel(); -} - } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testrunner.h b/plugins/autotest/testrunner.h index 53d0470c08a..a5e472d2237 100644 --- a/plugins/autotest/testrunner.h +++ b/plugins/autotest/testrunner.h @@ -47,10 +47,10 @@ signals: void testRunStarted(); void testRunFinished(); void testResultCreated(const TestResult &testResult); + void requestStopTestRun(); public slots: void runTests(); - void stopTestRun(); private slots: void buildProject(ProjectExplorer::Project *project); From 003f81245650a0549487744eda5dba065c68969f Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Tue, 13 Jan 2015 11:26:13 +0100 Subject: [PATCH 045/200] avoid abbreviations in variable names Change-Id: Ie9474da2a4c9c2e461bdd15e859e1a53f820a1d1 Reviewed-by: Christian Stenger --- plugins/autotest/testrunner.cpp | 94 ++++++++++++++++----------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 3d2f37533c5..824d17f6d22 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -168,20 +168,20 @@ static bool xmlExtractBenchmarkInformation(const QString &code, const QString &t const double value = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start).toDouble(); start = code.indexOf(QLatin1String(" iterations=\"")) + 13; const int iterations = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start).toInt(); - QString metricsTxt; + QString metricsText; if (metric == QLatin1String("WalltimeMilliseconds")) // default - metricsTxt = QLatin1String("msecs"); + metricsText = QLatin1String("msecs"); else if (metric == QLatin1String("CPUTicks")) // -tickcounter - metricsTxt = QLatin1String("CPU ticks"); + metricsText = QLatin1String("CPU ticks"); else if (metric == QLatin1String("Events")) // -eventcounter - metricsTxt = QLatin1String("events"); + metricsText = QLatin1String("events"); else if (metric == QLatin1String("InstructionReads")) // -callgrind - metricsTxt = QLatin1String("instruction reads"); + metricsText = QLatin1String("instruction reads"); else if (metric == QLatin1String("CPUCycles")) // -perf - metricsTxt = QLatin1String("CPU cycles"); + metricsText = QLatin1String("CPU cycles"); description = QObject::tr("%1 %2 per iteration (total: %3, iterations: %4)") .arg(formatResult(value)) - .arg(metricsTxt) + .arg(metricsText) .arg(formatResult(value * (double)iterations)) .arg(iterations); return true; @@ -211,7 +211,7 @@ void processOutput(QProcess *testRunner) static bool readingDescription = false; static QString qtVersion; static QString qtestVersion; - static QString bmDescription; + static QString benchmarkDescription; while (testRunner->canReadLine()) { // TODO Qt5 uses UTF-8 - while Qt4 uses ISO-8859-1 - could this be a problem? @@ -259,8 +259,8 @@ void processOutput(QProcess *testRunner) } continue; } - if (xmlExtractBenchmarkInformation(line, QLatin1String(" &future, const QListsetProgressRange(0, testCaseCount); m_currentFuture->setProgressValue(0); - foreach (const TestConfiguration *tc, selectedTests) { + foreach (const TestConfiguration *testConfiguration, selectedTests) { if (m_currentFuture->isCanceled()) break; - QString command = tc->targetFile(); - QString workingDirectory = tc->workingDirectory(); + QString command = testConfiguration->targetFile(); + QString workingDirectory = testConfiguration->workingDirectory(); QStringList argumentList; - Utils::Environment environment = tc->environment(); + Utils::Environment environment = testConfiguration->environment(); argumentList << QLatin1String("-xml"); if (!metricsOption.isEmpty()) argumentList << metricsOption; - if (tc->testCases().count()) - argumentList << tc->testCases(); - QString runCmd; + if (testConfiguration->testCases().count()) + argumentList << testConfiguration->testCases(); + QString runCommand; if (!QDir::toNativeSeparators(command).contains(QDir::separator())) { if (environment.hasKey(QLatin1String("PATH"))) - runCmd = which(environment.value(QLatin1String("PATH")), command); + runCommand = which(environment.value(QLatin1String("PATH")), command); } else if (QFileInfo(command).exists()) { - runCmd = command; + runCommand = command; } - if (runCmd.isEmpty()) { + if (runCommand.isEmpty()) { emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, QObject::tr("*** Could not find command '%1' ***").arg(command))); continue; @@ -388,9 +388,9 @@ void performTestRun(QFutureInterface &future, const QListhasActiveBuildSettings()) { TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_FATAL, tr("*** Project is not configured - canceling Test Run ***"))); @@ -498,18 +498,18 @@ void TestRunner::buildProject(ProjectExplorer::Project *project) { m_building = true; m_buildSucceeded = false; - ProjectExplorer::BuildManager *mgr = static_cast( + ProjectExplorer::BuildManager *buildManager = static_cast( ProjectExplorer::BuildManager::instance()); - connect(mgr, &ProjectExplorer::BuildManager::buildQueueFinished, + connect(buildManager, &ProjectExplorer::BuildManager::buildQueueFinished, this, &TestRunner::buildFinished); ProjectExplorer::ProjectExplorerPlugin::buildProject(project); } void TestRunner::buildFinished(bool success) { - ProjectExplorer::BuildManager *mgr = static_cast( + ProjectExplorer::BuildManager *buildManager = static_cast( ProjectExplorer::BuildManager::instance()); - disconnect(mgr, &ProjectExplorer::BuildManager::buildQueueFinished, + disconnect(buildManager, &ProjectExplorer::BuildManager::buildQueueFinished, this, &TestRunner::buildFinished); m_building = false; m_buildSucceeded = success; From 33ce9f9e0da3282ebd33655a8aa8b7752c7485b0 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Fri, 16 Jan 2015 11:53:33 +0100 Subject: [PATCH 046/200] refactor performTestRun On windows we are only interested in .exe files. For example QProcess("test.cmd") does not work. renamed which to executableFilePath Change-Id: Ib9aa2d011c3d0525b618a1b0a6bd32b556c02010 Reviewed-by: Christian Stenger --- plugins/autotest/testrunner.cpp | 92 ++++++++++++++------------------- 1 file changed, 38 insertions(+), 54 deletions(-) diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 824d17f6d22..ec142c9ec05 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -302,34 +302,31 @@ void processOutput(QProcess *testRunner) } } -static QString which(const QString &pathValue, const QString &command) +static QString executableFilePath(const QString &command, const QProcessEnvironment &environment) { - if (pathValue.isEmpty() || command.isEmpty()) + if (command.isEmpty()) return QString(); - QStringList pathList; -#ifdef Q_OS_WIN - pathList = pathValue.split(QLatin1Char(';')); -#else - pathList = pathValue.split(QLatin1Char(':')); -#endif + QFileInfo commandFileInfo(command); + if (commandFileInfo.isExecutable() && commandFileInfo.path() != QLatin1String(".")) { + return commandFileInfo.absoluteFilePath(); + } else if (commandFileInfo.path() == QLatin1String(".")){ + QString fullCommandFileName = command; + #ifdef Q_OS_WIN + if (!command.endsWith(QLatin1String(".exe"))) + fullCommandFileName = command + QLatin1String(".exe"); - foreach (const QString &path, pathList) { - const QString filePath = path + QDir::separator() + command; - QFileInfo commandFileInfo(filePath); - if (commandFileInfo.exists() && commandFileInfo.isExecutable()) - return filePath; -#ifdef Q_OS_WIN - commandFileInfo = QFileInfo(filePath + QLatin1String(".exe")); - if (commandFileInfo.exists()) - return commandFileInfo.absoluteFilePath(); - commandFileInfo = QFileInfo(filePath + QLatin1String(".bat")); - if (commandFileInfo.exists()) - return commandFileInfo.absoluteFilePath(); - commandFileInfo = QFileInfo(filePath + QLatin1String(".cmd")); - if (commandFileInfo.exists()) - return commandFileInfo.absoluteFilePath(); -#endif + static const QString pathSeparator(QLatin1Char(';')); + #else + static const QString pathSeparator(QLatin1Char(':')); + #endif + QStringList pathList = environment.value(QLatin1String("PATH")).split(pathSeparator); + + foreach (const QString &path, pathList) { + QString filePath(path + QDir::separator() + fullCommandFileName); + if (QFileInfo(filePath).isExecutable()) + return commandFileInfo.absoluteFilePath(); + } } return QString(); } @@ -344,9 +341,8 @@ void performTestRun(QFutureInterface &future, const QListcancel(); + QObject::connect(testRunner, &TestRunner::requestStopTestRun, &testProcess, [&] () { + future.cancel(); // this kills the process if that is still in the running loop }); QObject::connect(&testProcess, &QProcess::readyReadStandardOutput, [&] () { @@ -359,41 +355,29 @@ void performTestRun(QFutureInterface &future, const QListisCanceled()) break; - QString command = testConfiguration->targetFile(); - QString workingDirectory = testConfiguration->workingDirectory(); - QStringList argumentList; - Utils::Environment environment = testConfiguration->environment(); - argumentList << QLatin1String("-xml"); + QProcessEnvironment environment = testConfiguration->environment().toProcessEnvironment(); + QString commandFilePath = executableFilePath(testConfiguration->targetFile(), environment); + if (commandFilePath.isEmpty()) { + emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, + QObject::tr("*** Could not find command '%1' ***").arg(testConfiguration->targetFile()))); + continue; + } + + QStringList argumentList(QLatin1String("-xml")); if (!metricsOption.isEmpty()) argumentList << metricsOption; if (testConfiguration->testCases().count()) argumentList << testConfiguration->testCases(); - QString runCommand; - if (!QDir::toNativeSeparators(command).contains(QDir::separator())) { - if (environment.hasKey(QLatin1String("PATH"))) - runCommand = which(environment.value(QLatin1String("PATH")), command); - } else if (QFileInfo(command).exists()) { - runCommand = command; - } + testProcess.setArguments(argumentList); - if (runCommand.isEmpty()) { - emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, - QObject::tr("*** Could not find command '%1' ***").arg(command))); - continue; - } - - testProcess.setWorkingDirectory(workingDirectory); - testProcess.setProcessEnvironment(environment.toProcessEnvironment()); - QTime executionTimer; - - if (argumentList.count()) { - testProcess.start(runCommand, argumentList); - } else { - testProcess.start(runCommand); - } + testProcess.setWorkingDirectory(testConfiguration->workingDirectory()); + testProcess.setProcessEnvironment(environment); + testProcess.setProgram(commandFilePath); + testProcess.start(); bool ok = testProcess.waitForStarted(); + QTime executionTimer; executionTimer.start(); if (ok) { while (testProcess.state() == QProcess::Running && executionTimer.elapsed() < timeout) { From 2a78ffea8d9514b147167408269f0076c094fb70 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Fri, 16 Jan 2015 11:56:15 +0100 Subject: [PATCH 047/200] refactor if clause Change-Id: I3ce6e711392f35c89dfcbecc3c8fcb8aca293602 Reviewed-by: Christian Stenger --- plugins/autotest/testtreemodel.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 7060203a418..e966446e9dd 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -342,17 +342,16 @@ static void addProjectInformation(TestConfiguration *config, const QString &file QList rcs = target->runConfigurations(); foreach (ProjectExplorer::RunConfiguration *rc, rcs) { - if (ProjectExplorer::LocalApplicationRunConfiguration *localRunConfiguration - = qobject_cast(rc)) { - if (localRunConfiguration->executable() == targetFile) { - hasDesktopTarget = true; - workDir = Utils::FileUtils::normalizePathName( - localRunConfiguration->workingDirectory()); - ProjectExplorer::EnvironmentAspect *envAsp - = localRunConfiguration->extraAspect(); - env = envAsp->environment(); - break; - } + ProjectExplorer::LocalApplicationRunConfiguration *localRunConfiguration + = qobject_cast(rc); + if (localRunConfiguration && localRunConfiguration->executable() == targetFile) { + hasDesktopTarget = true; + workDir = Utils::FileUtils::normalizePathName( + localRunConfiguration->workingDirectory()); + ProjectExplorer::EnvironmentAspect *envAsp + = localRunConfiguration->extraAspect(); + env = envAsp->environment(); + break; } } } From 295ad02f7e62b66dfcba73ac56b6c2f2c8ba6036 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Fri, 16 Jan 2015 13:44:24 +0100 Subject: [PATCH 048/200] introduce testxmloutputreader Change-Id: I5a77e8fd629343bc059a03e6c27f45103b96101a Reviewed-by: Christian Stenger --- plugins/autotest/autotest.pro | 6 +- plugins/autotest/testrunner.cpp | 310 ++++------------------- plugins/autotest/testxmloutputreader.cpp | 263 +++++++++++++++++++ plugins/autotest/testxmloutputreader.h | 56 ++++ 4 files changed, 366 insertions(+), 269 deletions(-) create mode 100644 plugins/autotest/testxmloutputreader.cpp create mode 100644 plugins/autotest/testxmloutputreader.h diff --git a/plugins/autotest/autotest.pro b/plugins/autotest/autotest.pro index 0366ffae461..ecc89345754 100644 --- a/plugins/autotest/autotest.pro +++ b/plugins/autotest/autotest.pro @@ -25,7 +25,8 @@ SOURCES += \ testtreeitemdelegate.cpp \ testsettings.cpp \ testsettingspage.cpp \ - testnavigationwidget.cpp + testnavigationwidget.cpp \ + testxmloutputreader.cpp HEADERS += \ testtreeview.h \ @@ -46,7 +47,8 @@ HEADERS += \ testtreeitemdelegate.h \ testsettings.h \ testsettingspage.h \ - testnavigationwidget.h + testnavigationwidget.h \ + testxmloutputreader.h RESOURCES += \ autotest.qrc diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index ec142c9ec05..df9ad92b73d 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -15,12 +15,13 @@ ** contact form at http://qt.digia.com ** ****************************************************************************/ +#include "testrunner.h" #include "autotestconstants.h" #include "autotestplugin.h" #include "testresultspane.h" -#include "testrunner.h" #include "testsettings.h" +#include "testxmloutputreader.h" #include // REMOVE @@ -42,266 +43,12 @@ namespace Autotest { namespace Internal { static TestRunner *m_instance = 0; -static QFutureInterface *m_currentFuture = 0; - -TestRunner *TestRunner::instance() -{ - if (!m_instance) - m_instance = new TestRunner; - return m_instance; -} - -TestRunner::TestRunner(QObject *parent) : - QObject(parent), - m_building(false), - m_executingTests(false) -{ -} - -TestRunner::~TestRunner() -{ - qDeleteAll(m_selectedTests); - m_selectedTests.clear(); - m_instance = 0; -} - -void TestRunner::setSelectedTests(const QList &selected) -{ - qDeleteAll(m_selectedTests); - m_selectedTests.clear(); - m_selectedTests = selected; -} - -/******************** XML line parser helper ********************/ - -static bool xmlStartsWith(const QString &code, const QString &start, QString &result) -{ - if (code.startsWith(start)) { - result = code.mid(start.length()); - result = result.left(result.indexOf(QLatin1Char('"'))); - result = result.left(result.indexOf(QLatin1String(""), index) - index); - return !result.isEmpty(); - } - return false; -} - -static bool xmlExtractTypeFileLine(const QString &code, const QString &tagStart, - Result::Type &result, QString &file, int &line) -{ - if (code.startsWith(tagStart)) { - int start = code.indexOf(QLatin1String(" type=\"")) + 7; - result = TestResult::resultFromString( - code.mid(start, code.indexOf(QLatin1Char('"'), start) - start)); - start = code.indexOf(QLatin1String(" file=\"")) + 7; - file = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start); - start = code.indexOf(QLatin1String(" line=\"")) + 7; - line = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start).toInt(); - return true; - } - return false; -} - -// adapted from qplaintestlogger.cpp -static QString formatResult(double value) -{ - if (value < 0 || value == NAN) - return QLatin1String("NAN"); - if (value == 0) - return QLatin1String("0"); - - int significantDigits = 0; - qreal divisor = 1; - - while (value / divisor >= 1) { - divisor *= 10; - ++significantDigits; - } - - QString beforeDecimalPoint = QString::number(value, 'f', 0); - QString afterDecimalPoint = QString::number(value, 'f', 20); - afterDecimalPoint.remove(0, beforeDecimalPoint.count() + 1); - - const int beforeUse = qMin(beforeDecimalPoint.count(), significantDigits); - const int beforeRemove = beforeDecimalPoint.count() - beforeUse; - - beforeDecimalPoint.chop(beforeRemove); - for (int i = 0; i < beforeRemove; ++i) - beforeDecimalPoint.append(QLatin1Char('0')); - - int afterUse = significantDigits - beforeUse; - if (beforeDecimalPoint == QLatin1String("0") && !afterDecimalPoint.isEmpty()) { - ++afterUse; - int i = 0; - while (i < afterDecimalPoint.count() && afterDecimalPoint.at(i) == QLatin1Char('0')) - ++i; - afterUse += i; - } - - const int afterRemove = afterDecimalPoint.count() - afterUse; - afterDecimalPoint.chop(afterRemove); - - QString result = beforeDecimalPoint; - if (afterUse > 0) - result.append(QLatin1Char('.')); - result += afterDecimalPoint; - - return result; -} - -static bool xmlExtractBenchmarkInformation(const QString &code, const QString &tagStart, - QString &description) -{ - if (code.startsWith(tagStart)) { - int start = code.indexOf(QLatin1String(" metric=\"")) + 9; - const QString metric = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start); - start = code.indexOf(QLatin1String(" value=\"")) + 8; - const double value = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start).toDouble(); - start = code.indexOf(QLatin1String(" iterations=\"")) + 13; - const int iterations = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start).toInt(); - QString metricsText; - if (metric == QLatin1String("WalltimeMilliseconds")) // default - metricsText = QLatin1String("msecs"); - else if (metric == QLatin1String("CPUTicks")) // -tickcounter - metricsText = QLatin1String("CPU ticks"); - else if (metric == QLatin1String("Events")) // -eventcounter - metricsText = QLatin1String("events"); - else if (metric == QLatin1String("InstructionReads")) // -callgrind - metricsText = QLatin1String("instruction reads"); - else if (metric == QLatin1String("CPUCycles")) // -perf - metricsText = QLatin1String("CPU cycles"); - description = QObject::tr("%1 %2 per iteration (total: %3, iterations: %4)") - .arg(formatResult(value)) - .arg(metricsText) - .arg(formatResult(value * (double)iterations)) - .arg(iterations); - return true; - } - return false; -} void emitTestResultCreated(const TestResult &testResult) { emit m_instance->testResultCreated(testResult); } -/****************** XML line parser helper end ******************/ - -void processOutput(QProcess *testRunner) -{ - if (!testRunner) - return; - static QString className; - static QString testCase; - static QString dataTag; - static Result::Type result = Result::UNKNOWN; - static QString description; - static QString file; - static int lineNumber = 0; - static QString duration; - static bool readingDescription = false; - static QString qtVersion; - static QString qtestVersion; - static QString benchmarkDescription; - - while (testRunner->canReadLine()) { - // TODO Qt5 uses UTF-8 - while Qt4 uses ISO-8859-1 - could this be a problem? - const QString line = QString::fromUtf8(testRunner->readLine()).trimmed(); - if (line.isEmpty() || line.startsWith(QLatin1String(""), dataTag)) - continue; - if (xmlCData(line, QLatin1String(""), description)) { - if (!line.endsWith(QLatin1String(""))) - readingDescription = true; - continue; - } - if (xmlExtractTypeFileLine(line, QLatin1String(""))) { - TestResult testResult(className, testCase, dataTag, result, description); - if (!file.isEmpty()) - file = QFileInfo(testRunner->workingDirectory(), file).canonicalFilePath(); - testResult.setFileName(file); - testResult.setLine(lineNumber); - emitTestResultCreated(testResult); - } - continue; - } - if (xmlExtractBenchmarkInformation(line, QLatin1String("") || line == QLatin1String("")) { - TestResult testResult(className, testCase, dataTag, result, description); - if (!file.isEmpty()) - file = QFileInfo(testRunner->workingDirectory(), file).canonicalFilePath(); - testResult.setFileName(file); - testResult.setLine(lineNumber); - emitTestResultCreated(testResult); - description = QString(); - } else if (line == QLatin1String("") && !duration.isEmpty()) { - TestResult testResult(className, testCase, QString(), Result::MESSAGE_INTERNAL, - QObject::tr("execution took %1ms").arg(duration)); - emitTestResultCreated(testResult); - m_currentFuture->setProgressValue(m_currentFuture->progressValue() + 1); - } else if (line == QLatin1String("") && !duration.isEmpty()) { - TestResult testResult(className, QString(), QString(), Result::MESSAGE_INTERNAL, - QObject::tr("Test execution took %1ms").arg(duration)); - emitTestResultCreated(testResult); - } else if (readingDescription) { - if (line.endsWith(QLatin1String("]]>"))) { - description.append(QLatin1Char('\n')); - description.append(line.left(line.indexOf(QLatin1String("]]>")))); - readingDescription = false; - } else { - description.append(QLatin1Char('\n')); - description.append(line); - } - } else if (xmlStartsWith(line, QLatin1String(""), qtVersion)) { - emitTestResultCreated(FaultyTestResult(Result::MESSAGE_INTERNAL, - QObject::tr("Qt Version: %1").arg(qtVersion))); - } else if (xmlStartsWith(line, QLatin1String(""), qtestVersion)) { - emitTestResultCreated(FaultyTestResult(Result::MESSAGE_INTERNAL, - QObject::tr("QTest Version: %1").arg(qtestVersion))); - } else { -// qDebug() << "Unhandled line:" << line; // TODO remove - } - } -} - static QString executableFilePath(const QString &command, const QProcessEnvironment &environment) { if (command.isEmpty()) @@ -331,29 +78,60 @@ static QString executableFilePath(const QString &command, const QProcessEnvironm return QString(); } -void performTestRun(QFutureInterface &future, const QList selectedTests, const int timeout, const QString metricsOption, TestRunner* testRunner) +TestRunner *TestRunner::instance() +{ + if (!m_instance) + m_instance = new TestRunner; + return m_instance; +} + +TestRunner::TestRunner(QObject *parent) : + QObject(parent), + m_building(false), + m_executingTests(false) +{ +} + +TestRunner::~TestRunner() +{ + qDeleteAll(m_selectedTests); + m_selectedTests.clear(); + m_instance = 0; +} + +void TestRunner::setSelectedTests(const QList &selected) +{ + qDeleteAll(m_selectedTests); + m_selectedTests.clear(); + m_selectedTests = selected; +} + +void performTestRun(QFutureInterface &futureInterface, const QList selectedTests, const int timeout, const QString metricsOption, TestRunner* testRunner) { int testCaseCount = 0; foreach (const TestConfiguration *config, selectedTests) testCaseCount += config->testCaseCount(); - m_currentFuture = &future; QProcess testProcess; testProcess.setReadChannelMode(QProcess::MergedChannels); testProcess.setReadChannel(QProcess::StandardOutput); QObject::connect(testRunner, &TestRunner::requestStopTestRun, &testProcess, [&] () { - future.cancel(); // this kills the process if that is still in the running loop + futureInterface.cancel(); // this kills the process if that is still in the running loop }); - QObject::connect(&testProcess, &QProcess::readyReadStandardOutput, [&] () { - processOutput(&testProcess); + TestXmlOutputReader xmlReader(&testProcess); + QObject::connect(&xmlReader, &TestXmlOutputReader::increaseProgress, [&] () { + futureInterface.setProgressValue(futureInterface.progressValue() + 1); }); + QObject::connect(&xmlReader, &TestXmlOutputReader::testResultCreated, &emitTestResultCreated); - m_currentFuture->setProgressRange(0, testCaseCount); - m_currentFuture->setProgressValue(0); + QObject::connect(&testProcess, &QProcess::readyRead, &xmlReader, &TestXmlOutputReader::processOutput); + + futureInterface.setProgressRange(0, testCaseCount); + futureInterface.setProgressValue(0); foreach (const TestConfiguration *testConfiguration, selectedTests) { - if (m_currentFuture->isCanceled()) + if (futureInterface.isCanceled()) break; QProcessEnvironment environment = testConfiguration->environment().toProcessEnvironment(); @@ -381,7 +159,7 @@ void performTestRun(QFutureInterface &future, const QListisCanceled()) { + if (futureInterface.isCanceled()) { testProcess.kill(); testProcess.waitForFinished(); emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, @@ -400,9 +178,7 @@ void performTestRun(QFutureInterface &future, const QListsetProgressValue(testCaseCount); - - m_currentFuture = 0; + futureInterface.setProgressValue(testCaseCount); } void TestRunner::runTests() diff --git a/plugins/autotest/testxmloutputreader.cpp b/plugins/autotest/testxmloutputreader.cpp new file mode 100644 index 00000000000..10b6ed02b9e --- /dev/null +++ b/plugins/autotest/testxmloutputreader.cpp @@ -0,0 +1,263 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "testxmloutputreader.h" +#include "testresult.h" + +#include +#include +#include +#include + +namespace Autotest { +namespace Internal { + +static bool xmlStartsWith(const QString &code, const QString &start, QString &result) +{ + if (code.startsWith(start)) { + result = code.mid(start.length()); + result = result.left(result.indexOf(QLatin1Char('"'))); + result = result.left(result.indexOf(QLatin1String(""), index) - index); + return !result.isEmpty(); + } + return false; +} + +static bool xmlExtractTypeFileLine(const QString &code, const QString &tagStart, + Result::Type &result, QString &file, int &line) +{ + if (code.startsWith(tagStart)) { + int start = code.indexOf(QLatin1String(" type=\"")) + 7; + result = TestResult::resultFromString( + code.mid(start, code.indexOf(QLatin1Char('"'), start) - start)); + start = code.indexOf(QLatin1String(" file=\"")) + 7; + file = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start); + start = code.indexOf(QLatin1String(" line=\"")) + 7; + line = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start).toInt(); + return true; + } + return false; +} + + +// adapted from qplaintestlogger.cpp +static QString formatResult(double value) +{ + //NAN is not supported with visual studio 2010 +// if (value < 0 || value == NAN) +// return QLatin1String("NAN"); + if (value == 0) + return QLatin1String("0"); + + int significantDigits = 0; + qreal divisor = 1; + + while (value / divisor >= 1) { + divisor *= 10; + ++significantDigits; + } + + QString beforeDecimalPoint = QString::number(value, 'f', 0); + QString afterDecimalPoint = QString::number(value, 'f', 20); + afterDecimalPoint.remove(0, beforeDecimalPoint.count() + 1); + + const int beforeUse = qMin(beforeDecimalPoint.count(), significantDigits); + const int beforeRemove = beforeDecimalPoint.count() - beforeUse; + + beforeDecimalPoint.chop(beforeRemove); + for (int i = 0; i < beforeRemove; ++i) + beforeDecimalPoint.append(QLatin1Char('0')); + + int afterUse = significantDigits - beforeUse; + if (beforeDecimalPoint == QLatin1String("0") && !afterDecimalPoint.isEmpty()) { + ++afterUse; + int i = 0; + while (i < afterDecimalPoint.count() && afterDecimalPoint.at(i) == QLatin1Char('0')) + ++i; + afterUse += i; + } + + const int afterRemove = afterDecimalPoint.count() - afterUse; + afterDecimalPoint.chop(afterRemove); + + QString result = beforeDecimalPoint; + if (afterUse > 0) + result.append(QLatin1Char('.')); + result += afterDecimalPoint; + + return result; +} + +static bool xmlExtractBenchmarkInformation(const QString &code, const QString &tagStart, + QString &description) +{ + if (code.startsWith(tagStart)) { + int start = code.indexOf(QLatin1String(" metric=\"")) + 9; + const QString metric = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start); + start = code.indexOf(QLatin1String(" value=\"")) + 8; + const double value = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start).toDouble(); + start = code.indexOf(QLatin1String(" iterations=\"")) + 13; + const int iterations = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start).toInt(); + QString metricsText; + if (metric == QLatin1String("WalltimeMilliseconds")) // default + metricsText = QLatin1String("msecs"); + else if (metric == QLatin1String("CPUTicks")) // -tickcounter + metricsText = QLatin1String("CPU ticks"); + else if (metric == QLatin1String("Events")) // -eventcounter + metricsText = QLatin1String("events"); + else if (metric == QLatin1String("InstructionReads")) // -callgrind + metricsText = QLatin1String("instruction reads"); + else if (metric == QLatin1String("CPUCycles")) // -perf + metricsText = QLatin1String("CPU cycles"); + description = QObject::tr("%1 %2 per iteration (total: %3, iterations: %4)") + .arg(formatResult(value)) + .arg(metricsText) + .arg(formatResult(value * (double)iterations)) + .arg(iterations); + return true; + } + return false; +} + +TestXmlOutputReader::TestXmlOutputReader(QProcess *testApplication) + :m_testApplication(testApplication) +{ + connect(m_testApplication, &QProcess::readyReadStandardOutput, + this, &TestXmlOutputReader::processOutput); +} + +TestXmlOutputReader::~TestXmlOutputReader() +{ +} + +void TestXmlOutputReader::processOutput() +{ + if (!m_testApplication || m_testApplication->state() != QProcess::Running) + return; + static QString className; + static QString testCase; + static QString dataTag; + static Result::Type result = Result::UNKNOWN; + static QString description; + static QString file; + static int lineNumber = 0; + static QString duration; + static bool readingDescription = false; + static QString qtVersion; + static QString qtestVersion; + static QString benchmarkDescription; + + while (m_testApplication->canReadLine()) { + // TODO Qt5 uses UTF-8 - while Qt4 uses ISO-8859-1 - could this be a problem? + const QString line = QString::fromUtf8(m_testApplication->readLine()).trimmed(); + if (line.isEmpty() || line.startsWith(QLatin1String(""), dataTag)) + continue; + if (xmlCData(line, QLatin1String(""), description)) { + if (!line.endsWith(QLatin1String(""))) + readingDescription = true; + continue; + } + if (xmlExtractTypeFileLine(line, QLatin1String(""))) { + TestResult testResult(className, testCase, dataTag, result, description); + if (!file.isEmpty()) + file = QFileInfo(m_testApplication->workingDirectory(), file).canonicalFilePath(); + testResult.setFileName(file); + testResult.setLine(lineNumber); + testResultCreated(testResult); + } + continue; + } + if (xmlExtractBenchmarkInformation(line, QLatin1String("") || line == QLatin1String("")) { + TestResult testResult(className, testCase, dataTag, result, description); + if (!file.isEmpty()) + file = QFileInfo(m_testApplication->workingDirectory(), file).canonicalFilePath(); + testResult.setFileName(file); + testResult.setLine(lineNumber); + testResultCreated(testResult); + description = QString(); + } else if (line == QLatin1String("") && !duration.isEmpty()) { + TestResult testResult(className, testCase, QString(), Result::MESSAGE_INTERNAL, + QObject::tr("execution took %1ms").arg(duration)); + testResultCreated(testResult); + emit increaseProgress(); + } else if (line == QLatin1String("") && !duration.isEmpty()) { + TestResult testResult(className, QString(), QString(), Result::MESSAGE_INTERNAL, + QObject::tr("Test execution took %1ms").arg(duration)); + testResultCreated(testResult); + } else if (readingDescription) { + if (line.endsWith(QLatin1String("]]>"))) { + description.append(QLatin1Char('\n')); + description.append(line.left(line.indexOf(QLatin1String("]]>")))); + readingDescription = false; + } else { + description.append(QLatin1Char('\n')); + description.append(line); + } + } else if (xmlStartsWith(line, QLatin1String(""), qtVersion)) { + testResultCreated(FaultyTestResult(Result::MESSAGE_INTERNAL, + QObject::tr("Qt Version: %1").arg(qtVersion))); + } else if (xmlStartsWith(line, QLatin1String(""), qtestVersion)) { + testResultCreated(FaultyTestResult(Result::MESSAGE_INTERNAL, + QObject::tr("QTest Version: %1").arg(qtestVersion))); + } else { +// qDebug() << "Unhandled line:" << line; // TODO remove + } + } +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/testxmloutputreader.h b/plugins/autotest/testxmloutputreader.h new file mode 100644 index 00000000000..6d15a2b885c --- /dev/null +++ b/plugins/autotest/testxmloutputreader.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef TESTXMLOUTPUTREADER_H +#define TESTXMLOUTPUTREADER_H + +#include + +#include +#include + +QT_BEGIN_NAMESPACE +class QXmlStreamReader; +class QIODevice; +class QProcess; +QT_END_NAMESPACE + +namespace Autotest { +namespace Internal { + +class TestXmlOutputReader : public QObject +{ + Q_OBJECT + +public: + TestXmlOutputReader(QProcess *testApplication); + ~TestXmlOutputReader(); + +public slots: + void processOutput(); +signals: + void testResultCreated(const TestResult &testResult); + void increaseProgress(); +private: + QProcess *m_testApplication; +}; + +} // namespace Internal +} // namespace Autotest + +#endif // TESTXMLOUTPUTREADER_H From 6571c85f3d6c3a3f7eb1ff982b1e4df92293e156 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Fri, 16 Jan 2015 11:55:55 +0100 Subject: [PATCH 049/200] fix that windows can find the file added missing .exe file suffix Change-Id: I537736a95de778e0a498c37d21baf0d717eb8c4d Reviewed-by: Christian Stenger --- plugins/autotest/testtreemodel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index e966446e9dd..560820c5865 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -34,6 +34,7 @@ #include #include +#include #include @@ -334,7 +335,7 @@ static void addProjectInformation(TestConfiguration *config, const QString &file ProjectExplorer::BuildTargetInfoList appTargets = target->applicationTargets(); foreach (const ProjectExplorer::BuildTargetInfo &bti, appTargets.list) { if (bti.isValid() && bti.projectFilePath.toString() == proFile) { - targetFile = bti.targetFilePath.toString(); + targetFile = Utils::HostOsInfo::withExecutableSuffix(bti.targetFilePath.toString()); targetName = bti.targetName; break; } From 41208f66aa50caf52e3b69797b7db498a45ded49 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 21 Jan 2015 11:03:50 +0100 Subject: [PATCH 050/200] Re-enable printing of NAN for execution time Change-Id: I50bfd95808c90a30501bdf32f484dd035cc2f30b Reviewed-by: Tim Jenssen --- plugins/autotest/testxmloutputreader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/autotest/testxmloutputreader.cpp b/plugins/autotest/testxmloutputreader.cpp index 10b6ed02b9e..193b716a267 100644 --- a/plugins/autotest/testxmloutputreader.cpp +++ b/plugins/autotest/testxmloutputreader.cpp @@ -69,8 +69,8 @@ static bool xmlExtractTypeFileLine(const QString &code, const QString &tagStart, static QString formatResult(double value) { //NAN is not supported with visual studio 2010 -// if (value < 0 || value == NAN) -// return QLatin1String("NAN"); + if (value < 0)// || value == NAN) + return QLatin1String("NAN"); if (value == 0) return QLatin1String("0"); From 2aa7ce735069f23462852567a375c3515a185872 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 27 Jan 2015 13:29:53 +0100 Subject: [PATCH 051/200] Make sure to get output on Windows when using Qt5.4 or higher Change-Id: Id69636f5a48f5423217c47c039d4522ef42cd2a3 Reviewed-by: Tim Jenssen --- plugins/autotest/testrunner.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index df9ad92b73d..af1b5e17032 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -150,6 +150,8 @@ void performTestRun(QFutureInterface &futureInterface, const QListworkingDirectory()); + if (Utils::HostOsInfo::isWindowsHost()) + environment.insert(QLatin1String("QT_LOGGING_TO_CONSOLE"), QLatin1String("1")); testProcess.setProcessEnvironment(environment); testProcess.setProgram(commandFilePath); testProcess.start(); From 3629aa904448d7f62aab00629156093ca0cd5c60 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 28 Jan 2015 13:01:07 +0100 Subject: [PATCH 052/200] Fetch current project always before accessing This fixes two different crashes when TestCodeParser tried to access m_currentProject, but the object this pointer was referencing had been deleted already. Change-Id: Ie59e027394e613a8ef1e4f32f97abed6e8cb007a Reviewed-by: Tim Jenssen --- plugins/autotest/testcodeparser.cpp | 54 +++++++++++++---------------- plugins/autotest/testcodeparser.h | 5 --- 2 files changed, 25 insertions(+), 34 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 46cc75ad4bf..6faa7d160d8 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -49,7 +49,6 @@ namespace Internal { TestCodeParser::TestCodeParser(TestTreeModel *parent) : QObject(parent), m_model(parent), - m_currentProject(0), m_parserEnabled(true), m_pendingUpdate(false) { @@ -70,6 +69,14 @@ void TestCodeParser::emitUpdateTestTree() QTimer::singleShot(1000, this, SLOT(updateTestTree())); } +ProjectExplorer::Project *currentProject() +{ + const ProjectExplorer::SessionManager *session = ProjectExplorer::SessionManager::instance(); + if (!session || !session->hasProjects()) + return 0; + return session->startupProject(); +} + void TestCodeParser::updateTestTree() { if (!m_parserEnabled) { @@ -83,29 +90,15 @@ void TestCodeParser::updateTestTree() clearMaps(); m_model->removeAllAutoTests(); m_model->removeAllQuickTests(); - const ProjectExplorer::SessionManager *session = ProjectExplorer::SessionManager::instance(); - if (!session || !session->hasProjects()) { - if (m_currentProject) { - if (QmakeProjectManager::QmakeProject *qmproj - = qobject_cast(m_currentProject)) { - disconnect(qmproj, &QmakeProjectManager::QmakeProject::proFilesEvaluated, - this, &TestCodeParser::onProFileEvaluated); - } - } - m_currentProject = 0; - return; - } - m_currentProject = session->startupProject(); - if (!m_currentProject) - return; - else { - if (QmakeProjectManager::QmakeProject *qmproj - = qobject_cast(m_currentProject)) { - connect(qmproj, &QmakeProjectManager::QmakeProject::proFilesEvaluated, - this, &TestCodeParser::onProFileEvaluated); + if (ProjectExplorer::Project *proj = currentProject()) { + if (auto qmakeProject = qobject_cast(proj)) { + connect(qmakeProject, &QmakeProjectManager::QmakeProject::proFilesEvaluated, + this, &TestCodeParser::onProFileEvaluated, Qt::UniqueConnection); } - } + } else + return; + scanForTests(); m_pendingUpdate = false; } @@ -568,7 +561,8 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr doc) void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &doc) { - if (!m_currentProject) + ProjectExplorer::Project *project = currentProject(); + if (!project) return; const QString fileName = doc->fileName(); if (m_cppDocMap.contains(fileName)) { @@ -577,7 +571,7 @@ void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &doc) qDebug("Skipped due revision equality"); // added to verify if this ever happens.. return; } - } else if (!m_currentProject->files(ProjectExplorer::Project::AllFiles).contains(fileName)) { + } else if (!project->files(ProjectExplorer::Project::AllFiles).contains(fileName)) { return; } checkDocumentForTestCode(doc); @@ -585,7 +579,8 @@ void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &doc) void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &doc) { - if (!m_currentProject) + ProjectExplorer::Project *project = currentProject(); + if (!project) return; const QString fileName = doc->fileName(); if (m_quickDocMap.contains(fileName)) { @@ -593,7 +588,7 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &doc) qDebug("Skipped due revision equality (QML)"); // added to verify this ever happens.... return; } - } else if (!m_currentProject->files(ProjectExplorer::Project::AllFiles).contains(fileName)) { + } else if (!project->files(ProjectExplorer::Project::AllFiles).contains(fileName)) { // what if the file is not listed inside the pro file, but will be used anyway? return; } @@ -627,7 +622,7 @@ void TestCodeParser::scanForTests(const QStringList &fileList) { QStringList list; if (fileList.isEmpty()) { - list = m_currentProject->files(ProjectExplorer::Project::AllFiles); + list = currentProject()->files(ProjectExplorer::Project::AllFiles); } else { list << fileList; } @@ -767,11 +762,12 @@ void TestCodeParser::onAllTasksFinished(Core::Id type) void TestCodeParser::onProFileEvaluated() { - if (!m_currentProject) + ProjectExplorer::Project *project = currentProject(); + if (!project) return; CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); - const QList pp = cppMM->projectInfo(m_currentProject).projectParts(); + const QList pp = cppMM->projectInfo(project).projectParts(); foreach (const CppTools::ProjectPart::Ptr &p, pp) { if (!p->selectedForBuilding) removeTestsIfNecessaryByProFile(p->projectFile); diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 02556243f61..8a78026857b 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -26,10 +26,6 @@ #include #include -namespace ProjectExplorer { -class Project; -} - namespace Core { class Id; } @@ -71,7 +67,6 @@ private: TestTreeModel *m_model; QMap m_cppDocMap; QMap m_quickDocMap; - ProjectExplorer::Project *m_currentProject; bool m_parserEnabled; bool m_pendingUpdate; }; From 834c52f48318caa9875c87914bcab9ab47e4eb2c Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 30 Jan 2015 12:19:01 +0100 Subject: [PATCH 053/200] Avoid crash when using wrongly created test tree Change-Id: I686f0cf285daeb3889161109964efd6e9ac47a40 Reviewed-by: Tim Jenssen --- plugins/autotest/testtreemodel.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 560820c5865..81e4d4bfc92 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -420,7 +420,7 @@ QList TestTreeModel::getAllTestCases() const QList TestTreeModel::getSelectedTests() const { QList result; - TestConfiguration *tc; + TestConfiguration *testConfiguration = 0; for (int row = 0, count = m_autoTestRootItem->childCount(); row < count; ++row) { TestTreeItem *child = m_autoTestRootItem->child(row); @@ -429,9 +429,9 @@ QList TestTreeModel::getSelectedTests() const case Qt::Unchecked: continue; case Qt::Checked: - tc = new TestConfiguration(child->name(), QStringList(), child->childCount()); - addProjectInformation(tc, child->filePath()); - result << tc; + testConfiguration = new TestConfiguration(child->name(), QStringList(), child->childCount()); + addProjectInformation(testConfiguration, child->filePath()); + result << testConfiguration; continue; case Qt::PartiallyChecked: default: @@ -444,9 +444,9 @@ QList TestTreeModel::getSelectedTests() const testCases << grandChild->name(); } - tc = new TestConfiguration(childName, testCases); - addProjectInformation(tc, child->filePath()); - result << tc; + testConfiguration = new TestConfiguration(childName, testCases); + addProjectInformation(testConfiguration, child->filePath()); + result << testConfiguration; } } // Quick Tests must be handled differently - need the calling cpp file to use this in @@ -461,7 +461,10 @@ QList TestTreeModel::getSelectedTests() const const TestTreeItem *grandChild = unnamed->child(childRow); const QString mainFile = grandChild->mainFile(); if (foundMains.contains(mainFile)) { - foundMains[mainFile]->setTestCaseCount(tc->testCaseCount() + 1); + QTC_ASSERT(testConfiguration, + qWarning() << "Illegal state (unnamed Quick Test listed as named)"; + return QList()); + foundMains[mainFile]->setTestCaseCount(testConfiguration->testCaseCount()); } else { TestConfiguration *tc = new TestConfiguration(QString(), QStringList()); tc->setTestCaseCount(1); From ca4b66e8adb8520098505b9be09fc72a6eb79856 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 27 Jan 2015 15:22:17 +0100 Subject: [PATCH 054/200] Refactor TestCodeParser Change-Id: I5fdb6429e8509468b7a710414af250ea6464d92d Reviewed-by: Tim Jenssen --- plugins/autotest/testcodeparser.cpp | 596 +++++++++++++++------------- plugins/autotest/testcodeparser.h | 18 +- plugins/autotest/testtreeitem.cpp | 8 + plugins/autotest/testtreeitem.h | 1 + 4 files changed, 333 insertions(+), 290 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 6faa7d160d8..9d3772394b3 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -53,10 +53,11 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent) m_pendingUpdate(false) { // connect to ProgressManager to post-pone test parsing when CppModelManager is parsing - Core::ProgressManager *pm = qobject_cast( - Core::ProgressManager::instance()); - connect(pm, &Core::ProgressManager::taskStarted, this, &TestCodeParser::onTaskStarted); - connect(pm, &Core::ProgressManager::allTasksFinished, this, &TestCodeParser::onAllTasksFinished); + auto progressManager = qobject_cast(Core::ProgressManager::instance()); + connect(progressManager, &Core::ProgressManager::taskStarted, + this, &TestCodeParser::onTaskStarted); + connect(progressManager, &Core::ProgressManager::allTasksFinished, + this, &TestCodeParser::onAllTasksFinished); } TestCodeParser::~TestCodeParser() @@ -91,8 +92,8 @@ void TestCodeParser::updateTestTree() m_model->removeAllAutoTests(); m_model->removeAllQuickTests(); - if (ProjectExplorer::Project *proj = currentProject()) { - if (auto qmakeProject = qobject_cast(proj)) { + if (ProjectExplorer::Project *project = currentProject()) { + if (auto qmakeProject = qobject_cast(project)) { connect(qmakeProject, &QmakeProjectManager::QmakeProject::proFilesEvaluated, this, &TestCodeParser::onProFileEvaluated, Qt::UniqueConnection); } @@ -200,10 +201,11 @@ static QString quickTestSrcDir(const CppTools::CppModelManager *cppMM, return QString(); } -static QString testClass(const CPlusPlus::Document::Ptr &doc) +static QString testClass(const CppTools::CppModelManager *modelManager, + CPlusPlus::Document::Ptr &document) { static const QByteArray qtTestMacros[] = {"QTEST_MAIN", "QTEST_APPLESS_MAIN", "QTEST_GUILESS_MAIN"}; - const QList macros = doc->macroUses(); + const QList macros = document->macroUses(); foreach (const CPlusPlus::Document::MacroUse ¯o, macros) { if (!macro.isFunctionLike()) @@ -211,10 +213,19 @@ static QString testClass(const CPlusPlus::Document::Ptr &doc) const QByteArray name = macro.macro().name(); if (name == qtTestMacros[0] || name == qtTestMacros[1] || name == qtTestMacros[2]) { const CPlusPlus::Document::Block arg = macro.arguments().at(0); - return QLatin1String(getFileContent(doc->fileName()).mid(arg.bytesBegin(), arg.bytesEnd() - arg.bytesBegin())); + return QLatin1String(getFileContent(document->fileName()) + .mid(arg.bytesBegin(), arg.bytesEnd() - arg.bytesBegin())); } } - return QString(); + // check if one has used a self-defined macro or QTest::qExec() directly + const CPlusPlus::Snapshot snapshot = modelManager->snapshot(); + const QByteArray fileContent = getFileContent(document->fileName()); + document = snapshot.preprocessedDocument(fileContent, document->fileName()); + document->check(); + CPlusPlus::AST *ast = document->translationUnit()->ast(); + TestAstVisitor astVisitor(document); + astVisitor.accept(ast); + return astVisitor.className(); } static QString quickTestName(const CPlusPlus::Document::Ptr &doc) @@ -228,7 +239,8 @@ static QString quickTestName(const CPlusPlus::Document::Ptr &doc) const QByteArray name = macro.macro().name(); if (name == qtTestMacros[0] || name == qtTestMacros[1] || name == qtTestMacros[2]) { CPlusPlus::Document::Block arg = macro.arguments().at(0); - return QLatin1String(getFileContent(doc->fileName()).mid(arg.bytesBegin(), arg.bytesEnd() - arg.bytesBegin())); + return QLatin1String(getFileContent(doc->fileName()) + .mid(arg.bytesBegin(), arg.bytesEnd() - arg.bytesBegin())); } } return QString(); @@ -268,323 +280,186 @@ static QList scanDirectoryForQuickTestQmlFiles(const QStri return foundDocs; } +static CPlusPlus::Document::Ptr declaringDocument(CPlusPlus::Document::Ptr doc, + const QString &testCaseName, + unsigned *line, unsigned *column) +{ + CPlusPlus::Document::Ptr declaringDoc = doc; + const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + CPlusPlus::TypeOfExpression typeOfExpr; + typeOfExpr.init(doc, cppMM->snapshot()); + + auto lookupItems = typeOfExpr(testCaseName.toUtf8(), doc->globalNamespace()); + if (lookupItems.size()) { + CPlusPlus::Class *toeClass = lookupItems.first().declaration()->asClass(); + if (toeClass) { + const QString declFileName = QLatin1String(toeClass->fileId()->chars(), + toeClass->fileId()->size()); + declaringDoc = cppMM->snapshot().document(declFileName); + *line = toeClass->line(); + *column = toeClass->column() - 1; + } + } + return declaringDoc; +} + +static TestTreeItem *constructTestTreeItem(const QString &fileName, + const QString &mainFile, // used for Quick Tests only + const QString &testCaseName, + int line, int column, + const QMap functions, + TestTreeItem *rootItem) +{ + TestTreeItem *treeItem = new TestTreeItem(testCaseName, fileName, TestTreeItem::TEST_CLASS, rootItem); + treeItem->setMainFile(mainFile); // used for Quick Tests only + treeItem->setLine(line); + treeItem->setColumn(column); + + foreach (const QString &functionName, functions.keys()) { + const TestCodeLocationAndType locationAndType = functions.value(functionName); + TestTreeItem *treeItemChild = new TestTreeItem(functionName, locationAndType.m_fileName, + locationAndType.m_type, treeItem); + treeItemChild->setLine(locationAndType.m_line); + treeItemChild->setColumn(locationAndType.m_column); + treeItem->appendChild(treeItemChild); + } + return treeItem; +} + /****** end of helpers ******/ -void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc) +void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr document) { - const QString file = doc->fileName(); - const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + const QString fileName = document->fileName(); + const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); - QList projParts = cppMM->projectPart(file); + QList projParts = modelManager->projectPart(fileName); if (projParts.size()) if (!projParts.at(0)->selectedForBuilding) { - removeTestsIfNecessary(file); + removeTestsIfNecessary(fileName); return; } - if (includesQtQuickTest(doc, cppMM)) { - handleQtQuickTest(doc); + if (includesQtQuickTest(document, modelManager)) { + handleQtQuickTest(document); return; } - if (includesQtTest(doc, cppMM) && qtTestLibDefined(cppMM, file)) { - QString tc(testClass(doc)); - if (tc.isEmpty()) { - // one might have used an approach without macros or defined own macros - const CPlusPlus::Snapshot snapshot = cppMM->snapshot(); - const QByteArray fileContent = getFileContent(file); - doc = snapshot.preprocessedDocument(fileContent, file); - doc->check(); - CPlusPlus::AST *ast = doc->translationUnit()->ast(); - TestAstVisitor astVisitor(doc); - astVisitor.accept(ast); - tc = astVisitor.className(); - } - if (!tc.isEmpty()) { - // construct the new/modified TestTreeItem + if (includesQtTest(document, modelManager) && qtTestLibDefined(modelManager, fileName)) { + QString testCaseName(testClass(modelManager, document)); + if (!testCaseName.isEmpty()) { + unsigned line = 0; + unsigned column = 0; + CPlusPlus::Document::Ptr declaringDoc = declaringDocument(document, testCaseName, + &line, &column); + if (declaringDoc.isNull()) + return; + + TestVisitor visitor(testCaseName); + visitor.accept(declaringDoc->globalNamespace()); + const QMap testFunctions = visitor.privateSlots(); + const QModelIndex autoTestRootIndex = m_model->index(0, 0); TestTreeItem *autoTestRootItem = static_cast(autoTestRootIndex.internalPointer()); - TestTreeItem *ttItem = new TestTreeItem(tc, file, TestTreeItem::TEST_CLASS, - autoTestRootItem); - QString declFileName; - CPlusPlus::TypeOfExpression toe; - toe.init(doc, cppMM->snapshot()); - CPlusPlus::Document::Ptr declaringDoc = doc; - const QList toeItems = toe(tc.toUtf8(), doc->globalNamespace()); - if (toeItems.size()) { - CPlusPlus::Class *toeClass = toeItems.first().declaration()->asClass(); - if (toeClass) { - declFileName = QLatin1String(toeClass->fileId()->chars(), - toeClass->fileId()->size()); - declaringDoc = cppMM->snapshot().document(declFileName); - ttItem->setFilePath(declFileName); - ttItem->setLine(toeClass->line()); - ttItem->setColumn(toeClass->column() - 1); - } - } - if (declaringDoc.isNull()) { - delete ttItem; - return; - } - TestVisitor myVisitor(tc); - myVisitor.accept(declaringDoc->globalNamespace()); - const QMap privSlots = myVisitor.privateSlots(); - foreach (const QString &privS, privSlots.keys()) { - const TestCodeLocationAndType locationAndType = privSlots.value(privS); - TestTreeItem *ttSub = new TestTreeItem(privS, locationAndType.m_fileName, - locationAndType.m_type, ttItem); - ttSub->setLine(locationAndType.m_line); - ttSub->setColumn(locationAndType.m_column); - ttItem->appendChild(ttSub); - } - // TODO refactoring? - // update model and internal map - QString proFile; - QList ppList = cppMM->projectPart(file); - if (ppList.size()) - proFile = ppList.at(0)->projectFile; - - TestInfo info; - int count; - if (m_cppDocMap.contains(file)) { - info = m_cppDocMap.value(file); - count = autoTestRootItem->childCount(); - for (int i = 0; i < count; ++i) { - TestTreeItem *currentItem = autoTestRootItem->child(i); - if (currentItem->filePath() == file) { - m_model->modifyAutoTestSubtree(i, ttItem); - TestInfo ti(tc, privSlots.keys(), doc->revision(), doc->editorRevision()); - ti.setProfile(proFile); - m_cppDocMap.insert(file, ti); - break; - } + TestTreeItem *ttItem = constructTestTreeItem(declaringDoc->fileName(), QString(), + testCaseName, line, column, testFunctions, + autoTestRootItem); + updateModelAndCppDocMap(document, declaringDoc->fileName(), ttItem, autoTestRootItem); + } else { + // could not find the class to test, but QTest is included and QT_TESTLIB_LIB defined + // maybe file is only a referenced file + if (m_cppDocMap.contains(fileName)) { + const TestInfo info = m_cppDocMap[fileName]; + CPlusPlus::Snapshot snapshot = modelManager->snapshot(); + if (snapshot.contains(info.referencingFile())) { + checkDocumentForTestCode(snapshot.find(info.referencingFile()).value()); + } else { // no referencing file too, so this test case is no more a test case + m_model->removeAutoTestSubtreeByFilePath(fileName); + m_cppDocMap.remove(fileName); } - if (declFileName != file) { - info = m_cppDocMap.value(declFileName); - count = autoTestRootItem->childCount(); - for (int i = 0; i < count; ++i) { - TestTreeItem *currentItem = autoTestRootItem->child(i); - if (currentItem->filePath() == declFileName) { - m_model->modifyAutoTestSubtree(i, ttItem); - TestInfo ti(tc, privSlots.keys(), doc->revision(), - doc->editorRevision()); - ti.setReferencingFile(file); - ti.setProfile(proFile); - m_cppDocMap.insert(declFileName, ti); - break; - } - } - } - delete ttItem; - } else { - m_model->addAutoTest(ttItem); - TestInfo ti(tc, privSlots.keys(), doc->revision(), doc->editorRevision()); - ti.setProfile(proFile); - m_cppDocMap.insert(file, ti); - if (declFileName != file) { - TestInfo ti(tc, privSlots.keys(), doc->revision(), doc->editorRevision()); - ti.setReferencingFile(file); - ti.setProfile(proFile); - m_cppDocMap.insert(declFileName, ti); - } - } - } - } else { - // could not find the class to test, but QTest is included and QT_TESTLIB_LIB defined - // maybe file is only a referenced file - if (m_cppDocMap.contains(file)) { - const TestInfo info = m_cppDocMap[file]; - CPlusPlus::Snapshot snapshot = cppMM->snapshot(); - if (snapshot.contains(info.referencingFile())) { - checkDocumentForTestCode(snapshot.find(info.referencingFile()).value()); } } } } -void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr doc) +void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr document) { - const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); - if (quickTestName(doc).isEmpty()) + if (quickTestName(document).isEmpty()) return; - const QString srcDir = quickTestSrcDir(cppMM, doc->fileName()); + const QString fileName = document->fileName(); + const QString srcDir = quickTestSrcDir(modelManager, fileName); if (srcDir.isEmpty()) return; + const QModelIndex quickTestRootIndex = m_model->index(1, 0); + TestTreeItem *quickTestRootItem = static_cast(quickTestRootIndex.internalPointer()); + const QList qmlDocs = scanDirectoryForQuickTestQmlFiles(srcDir); - foreach (const QmlJS::Document::Ptr &d, qmlDocs) { - QmlJS::AST::Node *ast = d->ast(); + foreach (const QmlJS::Document::Ptr &qmlJSDoc, qmlDocs) { + QmlJS::AST::Node *ast = qmlJSDoc->ast(); if (!ast) { - qDebug() << "ast is zero pointer" << d->fileName(); // should not happen + qDebug() << "ast is zero pointer" << qmlJSDoc->fileName(); // should not happen continue; } - TestQmlVisitor qmlVisitor(d); + TestQmlVisitor qmlVisitor(qmlJSDoc); QmlJS::AST::Node::accept(ast, &qmlVisitor); - const QString tcName = qmlVisitor.testCaseName(); + const QString testCaseName = qmlVisitor.testCaseName(); const TestCodeLocationAndType tcLocationAndType = qmlVisitor.testCaseLocation(); const QMap testFunctions = qmlVisitor.testFunctions(); - const QModelIndex quickTestRootIndex = m_model->index(1, 0); - TestTreeItem *quickTestRootItem = static_cast(quickTestRootIndex.internalPointer()); - - if (tcName.isEmpty()) { - // if this test case was named before remove it - if (m_quickDocMap.contains(d->fileName())) { - m_model->removeQuickTestSubtreeByFilePath(d->fileName()); - m_quickDocMap.remove(d->fileName()); - } - TestTreeItem *unnamedQTItem = m_model->unnamedQuickTests(); - if (unnamedQTItem) { - // remove unnamed quick tests that are already found for this qml file - if (m_model->removeUnnamedQuickTests(d->fileName())) { - // make sure m_quickDocMap does not have a inconsistent state now - TestInfo ti = m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)]; - QStringList tiFunctions = ti.testFunctions(); - foreach (const QString &func, testFunctions.keys()) - tiFunctions.removeOne(func); - ti.setTestFunctions(tiFunctions); - if (tiFunctions.size() == 0) - m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); - else - m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), ti); - } - // as removeUnnamedQuickTests() could delete this item itself try to get it again - unnamedQTItem = m_model->unnamedQuickTests(); - } - // construct new/modified TestTreeItem - TestTreeItem *ttItem = new TestTreeItem(QString(), QString(), - TestTreeItem::TEST_CLASS, - quickTestRootItem); - if (unnamedQTItem) { - for (int i = 0, count = unnamedQTItem->childCount(); i < count; ++i) { - TestTreeItem *child = new TestTreeItem(*unnamedQTItem->child(i)); - child->setParent(ttItem); - ttItem->appendChild(child); - } - } - - foreach (const QString &func, testFunctions.keys()) { - const TestCodeLocationAndType locationAndType = testFunctions.value(func); - TestTreeItem *ttSub = new TestTreeItem(func, locationAndType.m_fileName, - locationAndType.m_type, ttItem); - ttSub->setLine(locationAndType.m_line); - ttSub->setColumn(locationAndType.m_column); - ttSub->setMainFile(doc->fileName()); - ttItem->appendChild(ttSub); - } - TestInfo info = m_quickDocMap.contains(tr(Constants::UNNAMED_QUICKTESTS)) - ? m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)] - : TestInfo(QString(), QStringList(), 666); - QStringList originalFunctions(info.testFunctions()); - foreach (const QString &func, testFunctions.keys()) - originalFunctions.append(func); - info.setTestFunctions(originalFunctions); - - if (unnamedQTItem) { - m_model->modifyQuickTestSubtree(unnamedQTItem->row(), ttItem); - delete ttItem; - } else { - m_model->addQuickTest(ttItem); - } - m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), info); - + if (testCaseName.isEmpty()) { + // remove found test functions before re-adding them + removeUnnamedQuickTests(qmlJSDoc->fileName(), testFunctions.keys()); + // re-create TestTreeItem for unnamed Quick Tests + recreateUnnamedQuickTest(testFunctions, fileName, quickTestRootItem); continue; } // end of handling test cases without name property // construct new/modified TestTreeItem - TestTreeItem *ttItem = new TestTreeItem(tcName, tcLocationAndType.m_fileName, - tcLocationAndType.m_type, quickTestRootItem); - ttItem->setLine(tcLocationAndType.m_line); - ttItem->setColumn(tcLocationAndType.m_column); - ttItem->setMainFile(doc->fileName()); - - foreach (const QString &func, testFunctions.keys()) { - const TestCodeLocationAndType locationAndType = testFunctions.value(func); - TestTreeItem *ttSub = new TestTreeItem(func, locationAndType.m_fileName, - locationAndType.m_type, ttItem); - ttSub->setLine(locationAndType.m_line); - ttSub->setColumn(locationAndType.m_column); - ttItem->appendChild(ttSub); - } + TestTreeItem *testTreeItem + = constructTestTreeItem(tcLocationAndType.m_fileName, fileName, testCaseName, + tcLocationAndType.m_line, tcLocationAndType.m_column, + testFunctions, quickTestRootItem); // update model and internal map - const QString fileName(tcLocationAndType.m_fileName); const QmlJS::Document::Ptr qmlDoc = - QmlJSTools::Internal::ModelManager::instance()->snapshot().document(fileName); - QString proFile; - QList ppList = cppMM->projectPart(doc->fileName()); - if (ppList.size()) - proFile = ppList.at(0)->projectFile; - - if (m_quickDocMap.contains(fileName)) { - for (int i = 0; i < quickTestRootItem->childCount(); ++i) { - if (quickTestRootItem->child(i)->filePath() == fileName) { - m_model->modifyQuickTestSubtree(i, ttItem); - TestInfo ti(tcName, testFunctions.keys(), 0, qmlDoc->editorRevision()); - ti.setReferencingFile(doc->fileName()); - ti.setProfile(proFile); - m_quickDocMap.insert(fileName, ti); - break; - } - } - delete ttItem; - } else { - // if it was formerly unnamed remove the respective items - if (m_quickDocMap.contains(tr(Constants::UNNAMED_QUICKTESTS))) { - if (m_model->removeUnnamedQuickTests(d->fileName())) { - // make sure m_quickDocMap does not have a inconsistent state now - TestInfo unnamedInfo = m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)]; - QStringList functions = unnamedInfo.testFunctions(); - foreach (const QString &func, testFunctions.keys()) - if (functions.contains(func)) - functions.removeOne(func); - unnamedInfo.setTestFunctions(functions); - if (functions.size() == 0) - m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); - else - m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), unnamedInfo); - } - } - - m_model->addQuickTest(ttItem); - TestInfo ti(tcName, testFunctions.keys(), 0, qmlDoc->editorRevision()); - ti.setReferencingFile(doc->fileName()); - ti.setProfile(proFile); - m_quickDocMap.insert(tcLocationAndType.m_fileName, ti); - } + QmlJSTools::Internal::ModelManager::instance()->snapshot().document(tcLocationAndType.m_fileName); + updateModelAndQuickDocMap(qmlDoc, qmlJSDoc->fileName(), fileName, testTreeItem, + quickTestRootItem); } } -void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &doc) +void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document) { ProjectExplorer::Project *project = currentProject(); if (!project) return; - const QString fileName = doc->fileName(); + const QString fileName = document->fileName(); if (m_cppDocMap.contains(fileName)) { - if (m_cppDocMap[fileName].revision() == doc->revision() - && m_cppDocMap[fileName].editorRevision() == doc->editorRevision()) { + if (m_cppDocMap[fileName].revision() == document->revision() + && m_cppDocMap[fileName].editorRevision() == document->editorRevision()) { qDebug("Skipped due revision equality"); // added to verify if this ever happens.. return; } } else if (!project->files(ProjectExplorer::Project::AllFiles).contains(fileName)) { return; } - checkDocumentForTestCode(doc); + checkDocumentForTestCode(document); } -void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &doc) +void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) { ProjectExplorer::Project *project = currentProject(); if (!project) return; - const QString fileName = doc->fileName(); + const QString fileName = document->fileName(); if (m_quickDocMap.contains(fileName)) { - if ((int)m_quickDocMap[fileName].editorRevision() == doc->editorRevision()) { + if ((int)m_quickDocMap[fileName].editorRevision() == document->editorRevision()) { qDebug("Skipped due revision equality (QML)"); // added to verify this ever happens.... return; } @@ -692,29 +567,28 @@ void TestCodeParser::removeTestsIfNecessary(const QString &fileName) } } - void TestCodeParser::removeTestsIfNecessaryByProFile(const QString &proFile) { - QList fl; - foreach (const QString &fn, m_cppDocMap.keys()) { - if (m_cppDocMap[fn].proFile() == proFile) - fl.append(fn); + QList fList; + foreach (const QString &fileName, m_cppDocMap.keys()) { + if (m_cppDocMap[fileName].proFile() == proFile) + fList.append(fileName); } - foreach (const QString &fn, fl) { - m_cppDocMap.remove(fn); - m_model->removeAutoTestSubtreeByFilePath(fn); + foreach (const QString &fileName, fList) { + m_cppDocMap.remove(fileName); + m_model->removeAutoTestSubtreeByFilePath(fileName); } - fl.clear(); - foreach (const QString &fn, m_quickDocMap.keys()) { - if (m_quickDocMap[fn].proFile() == proFile) - fl.append(fn); + fList.clear(); + foreach (const QString &fileName, m_quickDocMap.keys()) { + if (m_quickDocMap[fileName].proFile() == proFile) + fList.append(fileName); } - foreach (const QString &fn, fl) { - m_quickDocMap.remove(fn); - m_model->removeQuickTestSubtreeByFilePath(fn); + foreach (const QString &fileName, fList) { + m_quickDocMap.remove(fileName); + m_model->removeQuickTestSubtreeByFilePath(fileName); } // handle unnamed Quick Tests - fl.clear(); // will now be re-used as function names storage + fList.clear(); // will now be re-used as function names storage QSet filePaths; CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); if (TestTreeItem *unnamedQT = m_model->unnamedQuickTests()) { @@ -723,18 +597,18 @@ void TestCodeParser::removeTestsIfNecessaryByProFile(const QString &proFile) QList ppList = cppMM->projectPart(child->mainFile()); if (ppList.size() && ppList.at(0)->projectFile == proFile) { filePaths.insert(child->filePath()); - fl.append(child->name()); + fList.append(child->name()); } } } - foreach (const QString &fp, filePaths) { - m_model->removeUnnamedQuickTests(fp); + foreach (const QString &filePath, filePaths) { + m_model->removeUnnamedQuickTests(filePath); } // update info map TestInfo unnamedInfo = m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)]; QStringList functions = unnamedInfo.testFunctions(); - foreach (const QString &func, fl) - functions.removeOne(func); + foreach (const QString &function, fList) + functions.removeOne(function); unnamedInfo.setTestFunctions(functions); if (functions.size() == 0) m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); @@ -742,6 +616,74 @@ void TestCodeParser::removeTestsIfNecessaryByProFile(const QString &proFile) m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), unnamedInfo); } +void TestCodeParser::removeUnnamedQuickTests(const QString &fileName, + const QStringList &testFunctions) +{ + // if this test case was named before remove it + if (m_quickDocMap.contains(fileName)) { + m_model->removeQuickTestSubtreeByFilePath(fileName); + m_quickDocMap.remove(fileName); + } + + if (m_model->unnamedQuickTests()) { + // remove unnamed quick tests that are already found for this qml file + if (m_model->removeUnnamedQuickTests(fileName)) { + // make sure m_quickDocMap does not have a inconsistent state now + TestInfo testInfo = m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)]; + QStringList testFunctionNames = testInfo.testFunctions(); + foreach (const QString &func, testFunctions) + testFunctionNames.removeOne(func); + testInfo.setTestFunctions(testFunctionNames); + if (testFunctionNames.size() == 0) + m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); + else + m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), testInfo); + } + } +} + +void TestCodeParser::recreateUnnamedQuickTest(const QMap &testFunctions, + const QString &mainFile, TestTreeItem *rootItem) +{ + TestTreeItem *testTreeItem = new TestTreeItem(QString(), QString(), TestTreeItem::TEST_CLASS, + rootItem); + TestTreeItem *unnamedQTItem = m_model->unnamedQuickTests(); + // if there are still other unnamed Quick Tests re-parent them to the new + if (unnamedQTItem) { + for (int i = 0, count = unnamedQTItem->childCount(); i < count; ++i) { + TestTreeItem *child = new TestTreeItem(*unnamedQTItem->child(i)); + child->setParent(testTreeItem); + testTreeItem->appendChild(child); + } + } + // add test functions of the current + foreach (const QString &function, testFunctions.keys()) { + const TestCodeLocationAndType locationAndType = testFunctions.value(function); + TestTreeItem *testTreeFunction = new TestTreeItem(function, locationAndType.m_fileName, + locationAndType.m_type, testTreeItem); + testTreeFunction->setLine(locationAndType.m_line); + testTreeFunction->setColumn(locationAndType.m_column); + testTreeFunction->setMainFile(mainFile); + testTreeItem->appendChild(testTreeFunction); + } + + TestInfo info = m_quickDocMap.contains(tr(Constants::UNNAMED_QUICKTESTS)) + ? m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)] + : TestInfo(QString(), QStringList(), 666); + QStringList originalFunctions(info.testFunctions()); + foreach (const QString &function, testFunctions.keys()) + originalFunctions.append(function); + info.setTestFunctions(originalFunctions); + + if (unnamedQTItem) { + m_model->modifyQuickTestSubtree(unnamedQTItem->row(), testTreeItem); + delete testTreeItem; + } else { + m_model->addQuickTest(testTreeItem); + } + m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), info); +} + void TestCodeParser::onTaskStarted(Core::Id type) { if (type != CppTools::Constants::TASK_INDEX @@ -760,14 +702,96 @@ void TestCodeParser::onAllTasksFinished(Core::Id type) updateTestTree(); } +void TestCodeParser::updateModelAndCppDocMap(CPlusPlus::Document::Ptr document, + const QString &declFileName, + TestTreeItem *testItem, TestTreeItem *rootItem) +{ + const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + const QString fileName = document->fileName(); + const QString testCaseName = testItem->name(); + QString proFile; + const QList ppList = cppMM->projectPart(fileName); + if (ppList.size()) + proFile = ppList.at(0)->projectFile; + + if (m_cppDocMap.contains(fileName)) { + QStringList files = QStringList() << fileName; + if (fileName != declFileName) + files << declFileName; + foreach (const QString &file, files) { + const bool setReferencingFile = (files.size() == 2 && file == declFileName); + const int count = rootItem->childCount(); + for (int i = 0; i < count; ++i) { + TestTreeItem *currentItem = rootItem->child(i); + if (currentItem->filePath() == file) { + m_model->modifyAutoTestSubtree(i, testItem); + TestInfo testInfo(testCaseName, testItem->getChildNames(), + document->revision(), document->editorRevision()); + testInfo.setProfile(proFile); + if (setReferencingFile) + testInfo.setReferencingFile(fileName); + m_cppDocMap.insert(file, testInfo); + break; + } + } + } + delete testItem; // this item is no more needed as model updates the original with its content + } else { + m_model->addAutoTest(testItem); + TestInfo ti(testCaseName, testItem->getChildNames(), + document->revision(), document->editorRevision()); + ti.setProfile(proFile); + m_cppDocMap.insert(fileName, ti); + if (declFileName != fileName) { + ti.setReferencingFile(fileName); + m_cppDocMap.insert(declFileName, ti); + } + } +} + +void TestCodeParser::updateModelAndQuickDocMap(QmlJS::Document::Ptr qmlDoc, const QString ¤tQmlJSFile, + const QString &referencingFileName, + TestTreeItem *testItem, TestTreeItem *rootItem) +{ + const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + const QString fileName = qmlDoc->fileName(); + QString proFile; + QList ppList = cppMM->projectPart(referencingFileName); + if (ppList.size()) + proFile = ppList.at(0)->projectFile; + + if (m_quickDocMap.contains(fileName)) { + for (int i = 0; i < rootItem->childCount(); ++i) { + if (rootItem->child(i)->filePath() == fileName) { + m_model->modifyQuickTestSubtree(i, testItem); + TestInfo testInfo(testItem->name(), testItem->getChildNames(), 0, qmlDoc->editorRevision()); + testInfo.setReferencingFile(referencingFileName); + testInfo.setProfile(proFile); + m_quickDocMap.insert(fileName, testInfo); + break; + } + } + delete testItem; // this item is no more needed as model updates the original with its content + } else { + // if it was formerly unnamed remove the respective items + removeUnnamedQuickTests(currentQmlJSFile, testItem->getChildNames()); + + m_model->addQuickTest(testItem); + TestInfo testInfo(testItem->name(), testItem->getChildNames(), 0, qmlDoc->editorRevision()); + testInfo.setReferencingFile(referencingFileName); + testInfo.setProfile(proFile); + m_quickDocMap.insert(testItem->filePath(), testInfo); + } +} + void TestCodeParser::onProFileEvaluated() { ProjectExplorer::Project *project = currentProject(); if (!project) return; - CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); - const QList pp = cppMM->projectInfo(project).projectParts(); + CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); + const QList pp = modelManager->projectInfo(project).projectParts(); foreach (const CppTools::ProjectPart::Ptr &p, pp) { if (!p->selectedForBuilding) removeTestsIfNecessaryByProFile(p->projectFile); diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 8a78026857b..2c83433f0a4 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -33,8 +33,10 @@ class Id; namespace Autotest { namespace Internal { +struct TestCodeLocationAndType; class TestInfo; class TestTreeModel; +class TestTreeItem; class TestCodeParser : public QObject { @@ -48,11 +50,11 @@ signals: public slots: void emitUpdateTestTree(); void updateTestTree(); - void checkDocumentForTestCode(CPlusPlus::Document::Ptr doc); - void handleQtQuickTest(CPlusPlus::Document::Ptr doc); + void checkDocumentForTestCode(CPlusPlus::Document::Ptr document); + void handleQtQuickTest(CPlusPlus::Document::Ptr document); - void onCppDocumentUpdated(const CPlusPlus::Document::Ptr &doc); - void onQmlDocumentUpdated(const QmlJS::Document::Ptr &doc); + void onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document); + void onQmlDocumentUpdated(const QmlJS::Document::Ptr &document); void removeFiles(const QStringList &files); void onProFileEvaluated(); @@ -61,8 +63,16 @@ private: void clearMaps(); void removeTestsIfNecessary(const QString &fileName); void removeTestsIfNecessaryByProFile(const QString &proFile); + void removeUnnamedQuickTests(const QString &fileName, const QStringList &testFunctions); + void recreateUnnamedQuickTest(const QMap &testFunctions, + const QString &mainFile, TestTreeItem *rootItem); void onTaskStarted(Core::Id type); void onAllTasksFinished(Core::Id type); + void updateModelAndCppDocMap(CPlusPlus::Document::Ptr document, const QString &declFileName, + TestTreeItem *testItem, TestTreeItem *rootItem); + void updateModelAndQuickDocMap(QmlJS::Document::Ptr qmlDoc, const QString ¤tQmlJSFile, + const QString &referencingFileName, + TestTreeItem *testItem, TestTreeItem *rootItem); TestTreeModel *m_model; QMap m_cppDocMap; diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index 2da060da529..83983db2ef8 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -172,6 +172,14 @@ Qt::CheckState TestTreeItem::checked() const return Qt::Unchecked; } +QList TestTreeItem::getChildNames() const +{ + QList names; + foreach (TestTreeItem *item, m_children) + names << item->name(); + return names; +} + void TestTreeItem::revalidateCheckState() { if (m_children.size() == 0) diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index 8ec916b0bf5..411839a9bb4 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -64,6 +64,7 @@ public: Qt::CheckState checked() const; Type type() const { return m_type; } void setParent(TestTreeItem *parent) { m_parent = parent; } + QList getChildNames() const; private: void revalidateCheckState(); From 81e4659a085311e6dfa526554c203a49a07d5e2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20P=C3=B6nitz?= Date: Mon, 16 Feb 2015 13:12:50 +0100 Subject: [PATCH 055/200] Compile fix with current qtbase/dev Change-Id: I6fdb6429e8509468b7a710414af250ea6464d92d Reviewed-by: Christian Stenger --- plugins/autotest/testresult.h | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index 65b801d5d05..086b0fd21dc 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -21,6 +21,7 @@ #include #include +#include namespace Autotest { namespace Internal { From 9159799a2aaa4622471f6bf7eabb884989d4a9b3 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 16 Feb 2015 12:19:26 +0100 Subject: [PATCH 056/200] Fix modifyContent() to take type in account as well Change-Id: I1a4aeb10243afc5514330fceb3f502d9ea4432d1 Reviewed-by: Andre Poenitz --- plugins/autotest/testtreeitem.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index 83983db2ef8..ae6ab2e6710 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -133,6 +133,10 @@ bool TestTreeItem::modifyContent(const TestTreeItem *modified) m_mainFile = modified->m_mainFile; hasBeenModified = true; } + if (m_type != modified->m_type) { + m_type = modified->m_type; + hasBeenModified = true; + } return hasBeenModified; } From aba302ddefb95e009e05556a3cdec1a0d9d1b62c Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 5 Feb 2015 07:51:51 +0100 Subject: [PATCH 057/200] Fix compile warning Change-Id: Ib98f444baa1c35e038921b4e25927faee64f0877 Reviewed-by: Andre Poenitz --- plugins/autotest/testresult.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp index 810dcf2c43e..5e878955603 100644 --- a/plugins/autotest/testresult.cpp +++ b/plugins/autotest/testresult.cpp @@ -59,8 +59,7 @@ Result::Type TestResult::resultFromString(const QString &resultString) return Result::BLACKLISTED_PASS; if (resultString == QLatin1String("bfail")) return Result::BLACKLISTED_FAIL; - qDebug(" unexpected testresult..."); - qDebug(resultString.toLatin1()); + qDebug("Unexpected test result: %s", qPrintable(resultString)); return Result::UNKNOWN; } From 2ece8b61814a38a58e70f6209f3e6adf8657b481 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 5 Feb 2015 12:26:08 +0100 Subject: [PATCH 058/200] Fix detection of tests on OSX Change-Id: I662afadd17bd8b2f1fbc9269dc470430e871e582 Reviewed-by: Andre Poenitz --- plugins/autotest/testcodeparser.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 9d3772394b3..179698294f8 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -127,13 +127,19 @@ static QByteArray getFileContent(QString filePath) static bool includesQtTest(const CPlusPlus::Document::Ptr &doc, const CppTools::CppModelManager *cppMM) { + static QString expectedHeaderPrefix + = Utils::HostOsInfo::isMacHost() + ? QLatin1String("QtTest.framework/Headers") + : QLatin1String("QtTest"); + const QList includes = doc->resolvedIncludes(); foreach (const CPlusPlus::Document::Include &inc, includes) { // TODO this short cut works only for #include // bad, as there could be much more different approaches if (inc.unresolvedFileName() == QLatin1String("QtTest") - && inc.resolvedFileName().endsWith(QLatin1String("QtTest/QtTest"))) { + && inc.resolvedFileName().endsWith( + QString::fromLatin1("%1/QtTest").arg(expectedHeaderPrefix))) { return true; } } @@ -142,7 +148,8 @@ static bool includesQtTest(const CPlusPlus::Document::Ptr &doc, CPlusPlus::Snapshot snapshot = cppMM->snapshot(); const QSet allIncludes = snapshot.allIncludesForDocument(doc->fileName()); foreach (const QString &include, allIncludes) { - if (include.endsWith(QLatin1String("QtTest/qtest.h"))) { + + if (include.endsWith(QString::fromLatin1("%1/qtest.h").arg(expectedHeaderPrefix))) { return true; } } @@ -153,18 +160,24 @@ static bool includesQtTest(const CPlusPlus::Document::Ptr &doc, static bool includesQtQuickTest(const CPlusPlus::Document::Ptr &doc, const CppTools::CppModelManager *cppMM) { + static QString expectedHeaderPrefix + = Utils::HostOsInfo::isMacHost() + ? QLatin1String("QtQuickTest.framework/Headers") + : QLatin1String("QtQuickTest"); + const QList includes = doc->resolvedIncludes(); foreach (const CPlusPlus::Document::Include &inc, includes) { if (inc.unresolvedFileName() == QLatin1String("QtQuickTest/quicktest.h") - && inc.resolvedFileName().endsWith(QLatin1String("QtQuickTest/quicktest.h"))) { + && inc.resolvedFileName().endsWith( + QString::fromLatin1("%1/quicktest.h").arg(expectedHeaderPrefix))) { return true; } } if (cppMM) { foreach (const QString &include, cppMM->snapshot().allIncludesForDocument(doc->fileName())) { - if (include.endsWith(QLatin1String("QtQuickTest/quicktest.h"))) + if (include.endsWith(QString::fromLatin1("%1/quicktest.h").arg(expectedHeaderPrefix))) return true; } } From 61c50e4aa343387b56192a34db6384d1dfcfa3c5 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 5 Feb 2015 13:32:00 +0100 Subject: [PATCH 059/200] Fix wrong behavior for gathering test configuration If the current project mixed named and unnamed Quick tests determing the test configuration failed due to running into the assert if you had no auto tests for the current project selected as well. Change-Id: I5c98316fada704cd7e021becab897d168a19b99b Reviewed-by: Andre Poenitz --- plugins/autotest/testtreemodel.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 81e4d4bfc92..9c8d235a04b 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -464,13 +464,13 @@ QList TestTreeModel::getSelectedTests() const QTC_ASSERT(testConfiguration, qWarning() << "Illegal state (unnamed Quick Test listed as named)"; return QList()); - foundMains[mainFile]->setTestCaseCount(testConfiguration->testCaseCount()); + foundMains[mainFile]->setTestCaseCount(testConfiguration->testCaseCount() + 1); } else { - TestConfiguration *tc = new TestConfiguration(QString(), QStringList()); - tc->setTestCaseCount(1); - tc->setUnnamedOnly(true); - addProjectInformation(tc, mainFile); - foundMains.insert(mainFile, tc); + testConfiguration = new TestConfiguration(QString(), QStringList()); + testConfiguration->setTestCaseCount(1); + testConfiguration->setUnnamedOnly(true); + addProjectInformation(testConfiguration, mainFile); + foundMains.insert(mainFile, testConfiguration); } } } From 2ce99680b20802a370e6d20a1467a1d41fbee690 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 5 Feb 2015 16:07:45 +0100 Subject: [PATCH 060/200] Decouple code parser and model Additionally some minor refactorings to increase readability. Change-Id: I0be120fcedcf31dbb0116d84f0d3c23cf95e7d91 Reviewed-by: Andre Poenitz --- plugins/autotest/testcodeparser.cpp | 297 +++++++--------------- plugins/autotest/testcodeparser.h | 28 ++- plugins/autotest/testtreeitem.cpp | 2 +- plugins/autotest/testtreeitem.h | 9 +- plugins/autotest/testtreemodel.cpp | 371 ++++++++++++++++++---------- plugins/autotest/testtreemodel.h | 40 ++- plugins/autotest/testvisitor.h | 7 - 7 files changed, 387 insertions(+), 367 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 179698294f8..510ce09de29 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -19,8 +19,6 @@ #include "autotestconstants.h" #include "testcodeparser.h" #include "testinfo.h" -#include "testtreeitem.h" -#include "testtreemodel.h" #include "testvisitor.h" #include @@ -41,6 +39,7 @@ #include #include +#include #include namespace Autotest { @@ -89,8 +88,7 @@ void TestCodeParser::updateTestTree() qDebug("updating TestTreeModel"); clearMaps(); - m_model->removeAllAutoTests(); - m_model->removeAllQuickTests(); + emit cacheCleared(); if (ProjectExplorer::Project *project = currentProject()) { if (auto qmakeProject = qobject_cast(project)) { @@ -316,25 +314,24 @@ static CPlusPlus::Document::Ptr declaringDocument(CPlusPlus::Document::Ptr doc, return declaringDoc; } -static TestTreeItem *constructTestTreeItem(const QString &fileName, - const QString &mainFile, // used for Quick Tests only - const QString &testCaseName, - int line, int column, - const QMap functions, - TestTreeItem *rootItem) +static TestTreeItem constructTestTreeItem(const QString &fileName, + const QString &mainFile, // used for Quick Tests only + const QString &testCaseName, + int line, int column, + const QMap functions) { - TestTreeItem *treeItem = new TestTreeItem(testCaseName, fileName, TestTreeItem::TEST_CLASS, rootItem); - treeItem->setMainFile(mainFile); // used for Quick Tests only - treeItem->setLine(line); - treeItem->setColumn(column); + TestTreeItem treeItem(testCaseName, fileName, TestTreeItem::TEST_CLASS); + treeItem.setMainFile(mainFile); // used for Quick Tests only + treeItem.setLine(line); + treeItem.setColumn(column); foreach (const QString &functionName, functions.keys()) { const TestCodeLocationAndType locationAndType = functions.value(functionName); TestTreeItem *treeItemChild = new TestTreeItem(functionName, locationAndType.m_fileName, - locationAndType.m_type, treeItem); + locationAndType.m_type, &treeItem); treeItemChild->setLine(locationAndType.m_line); treeItemChild->setColumn(locationAndType.m_column); - treeItem->appendChild(treeItemChild); + treeItem.appendChild(treeItemChild); } return treeItem; } @@ -372,13 +369,9 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr document) visitor.accept(declaringDoc->globalNamespace()); const QMap testFunctions = visitor.privateSlots(); - const QModelIndex autoTestRootIndex = m_model->index(0, 0); - TestTreeItem *autoTestRootItem = static_cast(autoTestRootIndex.internalPointer()); - - TestTreeItem *ttItem = constructTestTreeItem(declaringDoc->fileName(), QString(), - testCaseName, line, column, testFunctions, - autoTestRootItem); - updateModelAndCppDocMap(document, declaringDoc->fileName(), ttItem, autoTestRootItem); + TestTreeItem item = constructTestTreeItem(declaringDoc->fileName(), QString(), + testCaseName, line, column, testFunctions); + updateModelAndCppDocMap(document, declaringDoc->fileName(), item); } else { // could not find the class to test, but QTest is included and QT_TESTLIB_LIB defined // maybe file is only a referenced file @@ -388,8 +381,8 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr document) if (snapshot.contains(info.referencingFile())) { checkDocumentForTestCode(snapshot.find(info.referencingFile()).value()); } else { // no referencing file too, so this test case is no more a test case - m_model->removeAutoTestSubtreeByFilePath(fileName); m_cppDocMap.remove(fileName); + emit testItemsRemoved(fileName, TestTreeModel::AutoTest); } } } @@ -403,21 +396,15 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr document) if (quickTestName(document).isEmpty()) return; - const QString fileName = document->fileName(); - const QString srcDir = quickTestSrcDir(modelManager, fileName); + const QString cppFileName = document->fileName(); + const QString srcDir = quickTestSrcDir(modelManager, cppFileName); if (srcDir.isEmpty()) return; - const QModelIndex quickTestRootIndex = m_model->index(1, 0); - TestTreeItem *quickTestRootItem = static_cast(quickTestRootIndex.internalPointer()); - const QList qmlDocs = scanDirectoryForQuickTestQmlFiles(srcDir); foreach (const QmlJS::Document::Ptr &qmlJSDoc, qmlDocs) { QmlJS::AST::Node *ast = qmlJSDoc->ast(); - if (!ast) { - qDebug() << "ast is zero pointer" << qmlJSDoc->fileName(); // should not happen - continue; - } + QTC_ASSERT(ast, continue); TestQmlVisitor qmlVisitor(qmlJSDoc); QmlJS::AST::Node::accept(ast, &qmlVisitor); @@ -426,24 +413,18 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr document) const QMap testFunctions = qmlVisitor.testFunctions(); if (testCaseName.isEmpty()) { - // remove found test functions before re-adding them - removeUnnamedQuickTests(qmlJSDoc->fileName(), testFunctions.keys()); - // re-create TestTreeItem for unnamed Quick Tests - recreateUnnamedQuickTest(testFunctions, fileName, quickTestRootItem); + updateUnnamedQuickTests(qmlJSDoc->fileName(), cppFileName, testFunctions); continue; } // end of handling test cases without name property // construct new/modified TestTreeItem - TestTreeItem *testTreeItem - = constructTestTreeItem(tcLocationAndType.m_fileName, fileName, testCaseName, + TestTreeItem testTreeItem + = constructTestTreeItem(tcLocationAndType.m_fileName, cppFileName, testCaseName, tcLocationAndType.m_line, tcLocationAndType.m_column, - testFunctions, quickTestRootItem); + testFunctions); // update model and internal map - const QmlJS::Document::Ptr qmlDoc = - QmlJSTools::Internal::ModelManager::instance()->snapshot().document(tcLocationAndType.m_fileName); - updateModelAndQuickDocMap(qmlDoc, qmlJSDoc->fileName(), fileName, testTreeItem, - quickTestRootItem); + updateModelAndQuickDocMap(qmlJSDoc, cppFileName, testTreeItem); } } @@ -489,15 +470,9 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) return; // special case of having unnamed TestCases - TestTreeItem *unnamed = m_model->unnamedQuickTests(); - for (int row = 0, count = unnamed->childCount(); row < count; ++row) { - const TestTreeItem *child = unnamed->child(row); - if (fileName == child->filePath()) { - if (snapshot.contains(child->mainFile())) - checkDocumentForTestCode(snapshot.document(child->mainFile())); - break; - } - } + const QString &mainFile = m_model->getMainFileForUnnamedQuickTest(fileName); + if (!mainFile.isEmpty() && snapshot.contains(mainFile)) + checkDocumentForTestCode(snapshot.document(mainFile)); } void TestCodeParser::removeFiles(const QStringList &files) @@ -537,7 +512,7 @@ void TestCodeParser::removeTestsIfNecessary(const QString &fileName) // check if this file was listed before and remove if necessary (switched config,...) if (m_cppDocMap.contains(fileName)) { m_cppDocMap.remove(fileName); - m_model->removeAutoTestSubtreeByFilePath(fileName); + emit testItemsRemoved(fileName, TestTreeModel::AutoTest); } else { // handle Qt Quick Tests QList toBeRemoved; foreach (const QString &file, m_quickDocMap.keys()) { @@ -551,21 +526,15 @@ void TestCodeParser::removeTestsIfNecessary(const QString &fileName) } foreach (const QString &file, toBeRemoved) { m_quickDocMap.remove(file); - m_model->removeQuickTestSubtreeByFilePath(file); + emit testItemsRemoved(file, TestTreeModel::QuickTest); } // unnamed Quick Tests must be handled separately QSet filePaths; QList functionNames; - if (TestTreeItem *unnamedQT = m_model->unnamedQuickTests()) { - for (int i = 0; i < unnamedQT->childCount(); ++i) { - const TestTreeItem *child = unnamedQT->child(i); - if (child->mainFile() == fileName) { - filePaths.insert(child->filePath()); - functionNames.append(child->name()); - } - } + if (m_model->hasUnnamedQuickTests()) { + m_model->qmlFilesAndFunctionNamesForMainFile(fileName, &filePaths, &functionNames); foreach (const QString &file, filePaths) - m_model->removeUnnamedQuickTests(file); + emit testItemsRemoved(file, TestTreeModel::QuickTest); // update info map TestInfo unnamedInfo = m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)]; QStringList functions = unnamedInfo.testFunctions(); @@ -576,6 +545,8 @@ void TestCodeParser::removeTestsIfNecessary(const QString &fileName) m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); else m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), unnamedInfo); + } else { + m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); } } } @@ -589,7 +560,7 @@ void TestCodeParser::removeTestsIfNecessaryByProFile(const QString &proFile) } foreach (const QString &fileName, fList) { m_cppDocMap.remove(fileName); - m_model->removeAutoTestSubtreeByFilePath(fileName); + emit testItemsRemoved(fileName, TestTreeModel::AutoTest); } fList.clear(); foreach (const QString &fileName, m_quickDocMap.keys()) { @@ -598,105 +569,23 @@ void TestCodeParser::removeTestsIfNecessaryByProFile(const QString &proFile) } foreach (const QString &fileName, fList) { m_quickDocMap.remove(fileName); - m_model->removeQuickTestSubtreeByFilePath(fileName); + emit testItemsRemoved(fileName, TestTreeModel::QuickTest); } // handle unnamed Quick Tests - fList.clear(); // will now be re-used as function names storage - QSet filePaths; - CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); - if (TestTreeItem *unnamedQT = m_model->unnamedQuickTests()) { - for (int i = 0; i < unnamedQT->childCount(); ++i) { - const TestTreeItem *child = unnamedQT->child(i); - QList ppList = cppMM->projectPart(child->mainFile()); - if (ppList.size() && ppList.at(0)->projectFile == proFile) { - filePaths.insert(child->filePath()); - fList.append(child->name()); - } - } - } - foreach (const QString &filePath, filePaths) { - m_model->removeUnnamedQuickTests(filePath); - } + const QSet &filePaths = m_model->qmlFilesForProFile(proFile); + foreach (const QString &fileName, filePaths) + emit unnamedQuickTestsRemoved(fileName); // update info map - TestInfo unnamedInfo = m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)]; - QStringList functions = unnamedInfo.testFunctions(); - foreach (const QString &function, fList) - functions.removeOne(function); - unnamedInfo.setTestFunctions(functions); - if (functions.size() == 0) + TestInfo unnamedInfo = m_quickDocMap.value(tr(Constants::UNNAMED_QUICKTESTS), + TestInfo(QString(), QStringList(), 666)); + + unnamedInfo.setTestFunctions(m_model->getUnnamedQuickTestFunctions()); + if (unnamedInfo.testFunctions().isEmpty()) m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); else m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), unnamedInfo); } -void TestCodeParser::removeUnnamedQuickTests(const QString &fileName, - const QStringList &testFunctions) -{ - // if this test case was named before remove it - if (m_quickDocMap.contains(fileName)) { - m_model->removeQuickTestSubtreeByFilePath(fileName); - m_quickDocMap.remove(fileName); - } - - if (m_model->unnamedQuickTests()) { - // remove unnamed quick tests that are already found for this qml file - if (m_model->removeUnnamedQuickTests(fileName)) { - // make sure m_quickDocMap does not have a inconsistent state now - TestInfo testInfo = m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)]; - QStringList testFunctionNames = testInfo.testFunctions(); - foreach (const QString &func, testFunctions) - testFunctionNames.removeOne(func); - testInfo.setTestFunctions(testFunctionNames); - if (testFunctionNames.size() == 0) - m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); - else - m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), testInfo); - } - } -} - -void TestCodeParser::recreateUnnamedQuickTest(const QMap &testFunctions, - const QString &mainFile, TestTreeItem *rootItem) -{ - TestTreeItem *testTreeItem = new TestTreeItem(QString(), QString(), TestTreeItem::TEST_CLASS, - rootItem); - TestTreeItem *unnamedQTItem = m_model->unnamedQuickTests(); - // if there are still other unnamed Quick Tests re-parent them to the new - if (unnamedQTItem) { - for (int i = 0, count = unnamedQTItem->childCount(); i < count; ++i) { - TestTreeItem *child = new TestTreeItem(*unnamedQTItem->child(i)); - child->setParent(testTreeItem); - testTreeItem->appendChild(child); - } - } - // add test functions of the current - foreach (const QString &function, testFunctions.keys()) { - const TestCodeLocationAndType locationAndType = testFunctions.value(function); - TestTreeItem *testTreeFunction = new TestTreeItem(function, locationAndType.m_fileName, - locationAndType.m_type, testTreeItem); - testTreeFunction->setLine(locationAndType.m_line); - testTreeFunction->setColumn(locationAndType.m_column); - testTreeFunction->setMainFile(mainFile); - testTreeItem->appendChild(testTreeFunction); - } - - TestInfo info = m_quickDocMap.contains(tr(Constants::UNNAMED_QUICKTESTS)) - ? m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)] - : TestInfo(QString(), QStringList(), 666); - QStringList originalFunctions(info.testFunctions()); - foreach (const QString &function, testFunctions.keys()) - originalFunctions.append(function); - info.setTestFunctions(originalFunctions); - - if (unnamedQTItem) { - m_model->modifyQuickTestSubtree(unnamedQTItem->row(), testTreeItem); - delete testTreeItem; - } else { - m_model->addQuickTest(testTreeItem); - } - m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), info); -} - void TestCodeParser::onTaskStarted(Core::Id type) { if (type != CppTools::Constants::TASK_INDEX @@ -715,13 +604,31 @@ void TestCodeParser::onAllTasksFinished(Core::Id type) updateTestTree(); } +void TestCodeParser::updateUnnamedQuickTests(const QString &fileName, const QString &mainFile, + const QMap &functions) +{ + // if this test case was named before remove it + m_quickDocMap.remove(fileName); + emit testItemsRemoved(fileName, TestTreeModel::QuickTest); + + emit unnamedQuickTestsUpdated(fileName, mainFile, functions); + + if (m_model->hasUnnamedQuickTests()) { + TestInfo info = m_quickDocMap.value(tr(Constants::UNNAMED_QUICKTESTS), + TestInfo(QString(), QStringList(), 666)); + info.setTestFunctions(m_model->getUnnamedQuickTestFunctions()); + m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), info); + } else { + m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); + } +} + void TestCodeParser::updateModelAndCppDocMap(CPlusPlus::Document::Ptr document, - const QString &declFileName, - TestTreeItem *testItem, TestTreeItem *rootItem) + const QString &declaringFile, TestTreeItem &testItem) { const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); const QString fileName = document->fileName(); - const QString testCaseName = testItem->name(); + const QString testCaseName = testItem.name(); QString proFile; const QList ppList = cppMM->projectPart(fileName); if (ppList.size()) @@ -729,71 +636,57 @@ void TestCodeParser::updateModelAndCppDocMap(CPlusPlus::Document::Ptr document, if (m_cppDocMap.contains(fileName)) { QStringList files = QStringList() << fileName; - if (fileName != declFileName) - files << declFileName; + if (fileName != declaringFile) + files << declaringFile; foreach (const QString &file, files) { - const bool setReferencingFile = (files.size() == 2 && file == declFileName); - const int count = rootItem->childCount(); - for (int i = 0; i < count; ++i) { - TestTreeItem *currentItem = rootItem->child(i); - if (currentItem->filePath() == file) { - m_model->modifyAutoTestSubtree(i, testItem); - TestInfo testInfo(testCaseName, testItem->getChildNames(), - document->revision(), document->editorRevision()); - testInfo.setProfile(proFile); - if (setReferencingFile) - testInfo.setReferencingFile(fileName); - m_cppDocMap.insert(file, testInfo); - break; - } - } + const bool setReferencingFile = (files.size() == 2 && file == declaringFile); + emit testItemModified(testItem, TestTreeModel::AutoTest, file); + TestInfo testInfo(testCaseName, testItem.getChildNames(), + document->revision(), document->editorRevision()); + testInfo.setProfile(proFile); + if (setReferencingFile) + testInfo.setReferencingFile(fileName); + m_cppDocMap.insert(file, testInfo); } - delete testItem; // this item is no more needed as model updates the original with its content } else { - m_model->addAutoTest(testItem); - TestInfo ti(testCaseName, testItem->getChildNames(), + emit testItemCreated(testItem, TestTreeModel::AutoTest); + TestInfo ti(testCaseName, testItem.getChildNames(), document->revision(), document->editorRevision()); ti.setProfile(proFile); m_cppDocMap.insert(fileName, ti); - if (declFileName != fileName) { + if (declaringFile != fileName) { ti.setReferencingFile(fileName); - m_cppDocMap.insert(declFileName, ti); + m_cppDocMap.insert(declaringFile, ti); } } } -void TestCodeParser::updateModelAndQuickDocMap(QmlJS::Document::Ptr qmlDoc, const QString ¤tQmlJSFile, - const QString &referencingFileName, - TestTreeItem *testItem, TestTreeItem *rootItem) +void TestCodeParser::updateModelAndQuickDocMap(QmlJS::Document::Ptr document, + const QString &referencingFile, + TestTreeItem &testItem) { const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); - const QString fileName = qmlDoc->fileName(); + const QString fileName = document->fileName(); QString proFile; - QList ppList = cppMM->projectPart(referencingFileName); + QList ppList = cppMM->projectPart(referencingFile); if (ppList.size()) proFile = ppList.at(0)->projectFile; if (m_quickDocMap.contains(fileName)) { - for (int i = 0; i < rootItem->childCount(); ++i) { - if (rootItem->child(i)->filePath() == fileName) { - m_model->modifyQuickTestSubtree(i, testItem); - TestInfo testInfo(testItem->name(), testItem->getChildNames(), 0, qmlDoc->editorRevision()); - testInfo.setReferencingFile(referencingFileName); - testInfo.setProfile(proFile); - m_quickDocMap.insert(fileName, testInfo); - break; - } - } - delete testItem; // this item is no more needed as model updates the original with its content + emit testItemModified(testItem, TestTreeModel::QuickTest, fileName); + TestInfo testInfo(testItem.name(), testItem.getChildNames(), 0, document->editorRevision()); + testInfo.setReferencingFile(referencingFile); + testInfo.setProfile(proFile); + m_quickDocMap.insert(fileName, testInfo); } else { // if it was formerly unnamed remove the respective items - removeUnnamedQuickTests(currentQmlJSFile, testItem->getChildNames()); + emit unnamedQuickTestsRemoved(fileName); - m_model->addQuickTest(testItem); - TestInfo testInfo(testItem->name(), testItem->getChildNames(), 0, qmlDoc->editorRevision()); - testInfo.setReferencingFile(referencingFileName); + emit testItemCreated(testItem, TestTreeModel::QuickTest); + TestInfo testInfo(testItem.name(), testItem.getChildNames(), 0, document->editorRevision()); + testInfo.setReferencingFile(referencingFile); testInfo.setProfile(proFile); - m_quickDocMap.insert(testItem->filePath(), testInfo); + m_quickDocMap.insert(testItem.filePath(), testInfo); } } diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 2c83433f0a4..e2f590cabf1 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -19,6 +19,9 @@ #ifndef TESTCODEPARSER_H #define TESTCODEPARSER_H +#include "testtreeitem.h" +#include "testtreemodel.h" + #include #include @@ -35,8 +38,6 @@ namespace Internal { struct TestCodeLocationAndType; class TestInfo; -class TestTreeModel; -class TestTreeItem; class TestCodeParser : public QObject { @@ -46,6 +47,14 @@ public: virtual ~TestCodeParser(); signals: + void cacheCleared(); + void testItemCreated(const TestTreeItem &item, TestTreeModel::Type type); + void testItemsCreated(const QList &itemList, TestTreeModel::Type type); + void testItemModified(TestTreeItem tItem, TestTreeModel::Type type, const QString &file); + void testItemsRemoved(const QString &filePath, TestTreeModel::Type type); + void unnamedQuickTestsUpdated(const QString &filePath, const QString &mainFile, + const QMap &functions); + void unnamedQuickTestsRemoved(const QString &filePath); public slots: void emitUpdateTestTree(); @@ -63,16 +72,15 @@ private: void clearMaps(); void removeTestsIfNecessary(const QString &fileName); void removeTestsIfNecessaryByProFile(const QString &proFile); - void removeUnnamedQuickTests(const QString &fileName, const QStringList &testFunctions); - void recreateUnnamedQuickTest(const QMap &testFunctions, - const QString &mainFile, TestTreeItem *rootItem); + void onTaskStarted(Core::Id type); void onAllTasksFinished(Core::Id type); - void updateModelAndCppDocMap(CPlusPlus::Document::Ptr document, const QString &declFileName, - TestTreeItem *testItem, TestTreeItem *rootItem); - void updateModelAndQuickDocMap(QmlJS::Document::Ptr qmlDoc, const QString ¤tQmlJSFile, - const QString &referencingFileName, - TestTreeItem *testItem, TestTreeItem *rootItem); + void updateUnnamedQuickTests(const QString &fileName, const QString &mainFile, + const QMap &functions); + void updateModelAndCppDocMap(CPlusPlus::Document::Ptr document, + const QString &declaringFile, TestTreeItem &testItem); + void updateModelAndQuickDocMap(QmlJS::Document::Ptr document, + const QString &referencingFile, TestTreeItem &testItem); TestTreeModel *m_model; QMap m_cppDocMap; diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index ae6ab2e6710..f3771183134 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -71,7 +71,7 @@ TestTreeItem::TestTreeItem(const TestTreeItem &other) } } -TestTreeItem *TestTreeItem::child(int row) +TestTreeItem *TestTreeItem::child(int row) const { return m_children.at(row); } diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index 411839a9bb4..25a49f3edf7 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -41,7 +41,7 @@ public: virtual ~TestTreeItem(); TestTreeItem(const TestTreeItem& other); - TestTreeItem *child(int row); + TestTreeItem *child(int row) const; TestTreeItem *parent() const; void appendChild(TestTreeItem *child); int row() const; @@ -80,6 +80,13 @@ private: QList m_children; }; +struct TestCodeLocationAndType { + QString m_fileName; + unsigned m_line; + unsigned m_column; + TestTreeItem::Type m_type; +}; + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 9c8d235a04b..f2ea94d6260 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -50,6 +50,17 @@ TestTreeModel::TestTreeModel(QObject *parent) : { m_rootItem->appendChild(m_autoTestRootItem); m_rootItem->appendChild(m_quickTestRootItem); + + connect(m_parser, &TestCodeParser::cacheCleared, this, &TestTreeModel::removeAllTestItems); + connect(m_parser, &TestCodeParser::testItemCreated, this, &TestTreeModel::addTestTreeItem); + connect(m_parser, &TestCodeParser::testItemsCreated, this, &TestTreeModel::addTestTreeItems); + connect(m_parser, &TestCodeParser::testItemModified, this, &TestTreeModel::modifyTestTreeItem); + connect(m_parser, &TestCodeParser::testItemsRemoved, this, &TestTreeModel::removeTestTreeItems); + connect(m_parser, &TestCodeParser::unnamedQuickTestsUpdated, + this, &TestTreeModel::updateUnnamedQuickTest); + connect(m_parser, &TestCodeParser::unnamedQuickTestsRemoved, + this, &TestTreeModel::removeUnnamedQuickTests); + m_parser->updateTestTree(); // CppTools::CppModelManagerInterface *cppMM = CppTools::CppModelManagerInterface::instance(); @@ -524,6 +535,62 @@ QList TestTreeModel::getSelectedTests() const return result; } +QString TestTreeModel::getMainFileForUnnamedQuickTest(const QString &qmlFile) const +{ + const TestTreeItem *unnamed = unnamedQuickTests(); + for (int row = 0, count = unnamed->childCount(); row < count; ++row) { + const TestTreeItem *child = unnamed->child(row); + if (qmlFile == child->filePath()) + return child->mainFile(); + } + return QString(); +} + +void TestTreeModel::qmlFilesAndFunctionNamesForMainFile(const QString &mainFile, + QSet *filePaths, + QList *functionNames) const +{ + TestTreeItem *unnamed = unnamedQuickTests(); + for (int i = 0; i < unnamed->childCount(); ++i) { + const TestTreeItem *child = unnamed->child(i); + if (child->mainFile() == mainFile) { + filePaths->insert(child->filePath()); + functionNames->append(child->name()); + } + } +} + +QList TestTreeModel::getUnnamedQuickTestFunctions() const +{ + TestTreeItem *unnamed = unnamedQuickTests(); + if (unnamed) + return unnamed->getChildNames(); + return QList(); +} + +QSet TestTreeModel::qmlFilesForProFile(const QString &proFile) const +{ + QSet filePaths; + CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); + if (TestTreeItem *unnamed = unnamedQuickTests()) { + for (int i = 0; i < unnamed->childCount(); ++i) { + const TestTreeItem *child = unnamed->child(i); + QList ppList = modelManager->projectPart(child->mainFile()); + if (ppList.size() && ppList.at(0)->projectFile == proFile) + filePaths.insert(child->filePath()); + } + } + return filePaths; +} + +bool TestTreeModel::hasUnnamedQuickTests() const +{ + for (int row = 0, count = m_quickTestRootItem->childCount(); row < count; ++row) + if (m_quickTestRootItem->child(row)->name().isEmpty()) + return true; + return false; +} + TestTreeItem *TestTreeModel::unnamedQuickTests() const { for (int row = 0, count = m_quickTestRootItem->childCount(); row < count; ++row) { @@ -534,177 +601,213 @@ TestTreeItem *TestTreeModel::unnamedQuickTests() const return 0; } -void TestTreeModel::modifyAutoTestSubtree(int row, TestTreeItem *newItem) -{ - QModelIndex toBeModifiedIndex = index(0, 0).child(row, 0); - modifyTestSubtree(toBeModifiedIndex, newItem); -} - -void TestTreeModel::removeAutoTestSubtreeByFilePath(const QString &file) -{ - const QModelIndex atRootIndex = index(0, 0); - const int count = rowCount(atRootIndex); - for (int row = 0; row < count; ++row) { - const QModelIndex childIndex = atRootIndex.child(row, 0); - TestTreeItem *childItem = static_cast(childIndex.internalPointer()); - if (file == childItem->filePath()) { - removeRow(row, atRootIndex); - break; - } - } - emit testTreeModelChanged(); -} - -void TestTreeModel::addAutoTest(TestTreeItem *newItem) -{ - beginInsertRows(index(0, 0), m_autoTestRootItem->childCount(), m_autoTestRootItem->childCount()); - m_autoTestRootItem->appendChild(newItem); - endInsertRows(); - emit testTreeModelChanged(); -} - -void TestTreeModel::removeAllAutoTests() -{ - beginResetModel(); - m_autoTestRootItem->removeChildren(); - endResetModel(); - emit testTreeModelChanged(); -} - -void TestTreeModel::modifyQuickTestSubtree(int row, TestTreeItem *newItem) -{ - QModelIndex toBeModifiedIndex = index(1, 0).child(row, 0); - modifyTestSubtree(toBeModifiedIndex, newItem); -} - -void TestTreeModel::removeQuickTestSubtreeByFilePath(const QString &file) -{ - const QModelIndex qtRootIndex = index(1, 0); - for (int row = 0, count = rowCount(qtRootIndex); row < count; ++row) { - const QModelIndex childIndex = qtRootIndex.child(row, 0); - const TestTreeItem *childItem = static_cast(childIndex.internalPointer()); - if (file == childItem->filePath()) { - removeRow(row, qtRootIndex); - break; - } - } - emit testTreeModelChanged(); -} - -void TestTreeModel::addQuickTest(TestTreeItem *newItem) -{ - beginInsertRows(index(1, 0), m_quickTestRootItem->childCount(), m_quickTestRootItem->childCount()); - m_quickTestRootItem->appendChild(newItem); - endInsertRows(); - emit testTreeModelChanged(); -} - -void TestTreeModel::removeAllQuickTests() -{ - beginResetModel(); - m_quickTestRootItem->removeChildren(); - endResetModel(); - emit testTreeModelChanged(); -} - -bool TestTreeModel::removeUnnamedQuickTests(const QString &filePath) +void TestTreeModel::removeUnnamedQuickTests(const QString &filePath) { TestTreeItem *unnamedQT = unnamedQuickTests(); if (!unnamedQT) - return false; + return; - bool removed = false; const QModelIndex unnamedQTIndex = index(1, 0).child(unnamedQT->row(), 0); for (int childRow = unnamedQT->childCount() - 1; childRow >= 0; --childRow) { const TestTreeItem *child = unnamedQT->child(childRow); if (filePath == child->filePath()) - removed |= removeRow(childRow, unnamedQTIndex); + removeRow(childRow, unnamedQTIndex); } if (unnamedQT->childCount() == 0) removeRow(unnamedQT->row(), unnamedQTIndex.parent()); emit testTreeModelChanged(); - return removed; } -void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, TestTreeItem *newItem) +void TestTreeModel::addTestTreeItem(const TestTreeItem &item, TestTreeModel::Type type) +{ + TestTreeItem *parent = rootItemForType(type); + QModelIndex index = rootIndexForType(type); + TestTreeItem *toBeAdded = new TestTreeItem(item); + toBeAdded->setParent(parent); + + beginInsertRows(index, parent->childCount(), parent->childCount()); + parent->appendChild(toBeAdded); + endInsertRows(); + emit testTreeModelChanged(); +} + +void TestTreeModel::addTestTreeItems(const QList &itemList, TestTreeModel::Type type) +{ + TestTreeItem *parent = rootItemForType(type); + QModelIndex index = rootIndexForType(type); + + beginInsertRows(index, parent->childCount(), parent->childCount() + itemList.size() - 1); + foreach (const TestTreeItem &item, itemList) { + TestTreeItem *toBeAdded = new TestTreeItem(item); + toBeAdded->setParent(parent); + parent->appendChild(toBeAdded); + } + endInsertRows(); + emit testTreeModelChanged(); +} + +void TestTreeModel::updateUnnamedQuickTest(const QString &fileName, const QString &mainFile, + const QMap &functions) +{ + removeUnnamedQuickTests(fileName); + TestTreeItem unnamed = hasUnnamedQuickTests() + ? TestTreeItem(*unnamedQuickTests()) + : TestTreeItem(QString(), QString(), TestTreeItem::TEST_CLASS, rootItemForType(QuickTest)); + + foreach (const QString &functionName, functions.keys()) { + const TestCodeLocationAndType locationAndType = functions.value(functionName); + TestTreeItem *testFunction = new TestTreeItem(functionName, locationAndType.m_fileName, + locationAndType.m_type, &unnamed); + testFunction->setLine(locationAndType.m_line); + testFunction->setColumn(locationAndType.m_column); + testFunction->setMainFile(mainFile); + unnamed.appendChild(testFunction); + } + if (hasUnnamedQuickTests()) + modifyTestTreeItem(unnamed, QuickTest, QString()); + else + addTestTreeItem(unnamed, QuickTest); +} + +void TestTreeModel::modifyTestTreeItem(TestTreeItem item, TestTreeModel::Type type, const QString &file) +{ + QModelIndex index = rootIndexForType(type); + TestTreeItem *parent = rootItemForType(type); + item.setParent(parent); + if (file.isEmpty()) { + if (TestTreeItem *unnamed = unnamedQuickTests()) { + index = index.child(unnamed->row(), 0); + modifyTestSubtree(index, item); + } + } else { + for (int row = 0; row < parent->childCount(); ++row) { + if (parent->child(row)->filePath() == file) { + index = index.child(row, 0); + modifyTestSubtree(index, item); + break; + } + } + } +} + +void TestTreeModel::removeAllTestItems() +{ + beginResetModel(); + m_autoTestRootItem->removeChildren(); + m_quickTestRootItem->removeChildren(); + endResetModel(); + emit testTreeModelChanged(); +} + +void TestTreeModel::removeTestTreeItems(const QString &filePath, Type type) +{ + bool removed = false; + const QModelIndex rootIndex = rootIndexForType(type); + const int count = rowCount(rootIndex); + for (int row = count - 1; row >= 0; --row) { + const QModelIndex childIndex = rootIndex.child(row, 0); + TestTreeItem *childItem = static_cast(childIndex.internalPointer()); + if (filePath == childItem->filePath()) + removed |= removeRow(row, rootIndex); + } + if (removed) + emit testTreeModelChanged(); +} + +TestTreeItem *TestTreeModel::rootItemForType(TestTreeModel::Type type) +{ + switch (type) { + case AutoTest: + return m_autoTestRootItem; + case QuickTest: + return m_quickTestRootItem; + } + QTC_ASSERT(false, return 0); +} + +QModelIndex TestTreeModel::rootIndexForType(TestTreeModel::Type type) +{ + switch (type) { + case AutoTest: + return index(0, 0); + case QuickTest: + return index(1, 0); + } + QTC_ASSERT(false, return QModelIndex()); +} + +void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, const TestTreeItem &newItem) + { if (!toBeModifiedIndex.isValid()) return; - static QVector modificationRoles = QVector() << Qt::DisplayRole - << Qt::ToolTipRole << LinkRole; TestTreeItem *toBeModifiedItem = static_cast(toBeModifiedIndex.internalPointer()); - if (toBeModifiedItem->modifyContent(newItem)) - emit dataChanged(toBeModifiedIndex, toBeModifiedIndex, modificationRoles); + if (toBeModifiedItem->modifyContent(&newItem)) + emit dataChanged(toBeModifiedIndex, toBeModifiedIndex, + QVector() << Qt::DisplayRole << Qt::ToolTipRole << LinkRole); // process sub-items as well... const int childCount = toBeModifiedItem->childCount(); - const int newChildCount = newItem->childCount(); + const int newChildCount = newItem.childCount(); // for keeping the CheckState on modifications - // TODO might still fail for duplicate entries (e.g. unnamed Quick Tests) - QHash originalItems; + // TODO might still fail for duplicate entries + QHash checkStates; for (int row = 0; row < childCount; ++row) { const TestTreeItem *child = toBeModifiedItem->child(row); - originalItems.insert(child->name(), child->checked()); + checkStates.insert(child->name(), child->checked()); } if (childCount <= newChildCount) { - for (int row = 0; row < childCount; ++row) { - QModelIndex child = toBeModifiedIndex.child(row, 0); - TestTreeItem *toBeModifiedChild = toBeModifiedItem->child(row); - TestTreeItem *modifiedChild = newItem->child(row); - if (toBeModifiedChild->modifyContent(modifiedChild)) { - emit dataChanged(child, child, modificationRoles); - } - if (originalItems.contains(toBeModifiedChild->name())) { - Qt::CheckState state = originalItems.value(toBeModifiedChild->name()); - if (state != toBeModifiedChild->checked()) { - toBeModifiedChild->setChecked(state); - emit dataChanged(child, child, QVector() << Qt::CheckStateRole); - } - } else { // newly added (BAD: happens for renaming as well) - toBeModifiedChild->setChecked(Qt::Checked); - emit dataChanged(child, child, QVector() << Qt::CheckStateRole); - } - } - if (childCount < newChildCount) { // add aditional items - for (int row = childCount; row < newChildCount; ++row) { - TestTreeItem *newChild = newItem->child(row); - TestTreeItem *toBeAdded = new TestTreeItem(*newChild); - toBeAdded->setParent(toBeModifiedItem); - beginInsertRows(toBeModifiedIndex, row, row); - toBeModifiedItem->appendChild(toBeAdded); - endInsertRows(); - if (originalItems.contains(toBeAdded->name()) - && originalItems.value(toBeAdded->name()) != Qt::Checked) - toBeAdded->setChecked(originalItems.value(toBeAdded->name())); - } + processChildren(toBeModifiedIndex, newItem, childCount, checkStates); + // add additional items + for (int row = childCount; row < newChildCount; ++row) { + TestTreeItem *newChild = newItem.child(row); + TestTreeItem *toBeAdded = new TestTreeItem(*newChild); + toBeAdded->setParent(toBeModifiedItem); + if (checkStates.contains(toBeAdded->name()) + && checkStates.value(toBeAdded->name()) != Qt::Checked) + toBeAdded->setChecked(checkStates.value(toBeAdded->name())); + beginInsertRows(toBeModifiedIndex, row, row); + toBeModifiedItem->appendChild(toBeAdded); + endInsertRows(); } } else { - for (int row = 0; row < newChildCount; ++row) { - QModelIndex child = toBeModifiedIndex.child(row, 0); - TestTreeItem *toBeModifiedChild = toBeModifiedItem->child(row); - TestTreeItem *modifiedChild = newItem->child(row); - if (toBeModifiedChild->modifyContent(modifiedChild)) - emit dataChanged(child, child, modificationRoles); - if (originalItems.contains(toBeModifiedChild->name())) { - Qt::CheckState state = originalItems.value(toBeModifiedChild->name()); - if (state != toBeModifiedChild->checked()) { - toBeModifiedChild->setChecked(state); - emit dataChanged(child, child, QVector() << Qt::CheckStateRole); - } - } else { // newly added (BAD: happens for renaming as well) - toBeModifiedChild->setChecked(Qt::Checked); - emit dataChanged(child, child, QVector() << Qt::CheckStateRole); - } - } // remove rest of the items + processChildren(toBeModifiedIndex, newItem, newChildCount, checkStates); + // remove rest of the items removeRows(newChildCount, childCount - newChildCount, toBeModifiedIndex); } emit testTreeModelChanged(); } +void TestTreeModel::processChildren(QModelIndex &parentIndex, const TestTreeItem &newItem, + const int upperBound, + const QHash &checkStates) +{ + static QVector modificationRoles = QVector() << Qt::DisplayRole + << Qt::ToolTipRole << LinkRole; + TestTreeItem *toBeModifiedItem = static_cast(parentIndex.internalPointer()); + for (int row = 0; row < upperBound; ++row) { + QModelIndex child = parentIndex.child(row, 0); + TestTreeItem *toBeModifiedChild = toBeModifiedItem->child(row); + TestTreeItem *modifiedChild = newItem.child(row); + if (toBeModifiedChild->modifyContent(modifiedChild)) + emit dataChanged(child, child, modificationRoles); + if (checkStates.contains(toBeModifiedChild->name())) { + Qt::CheckState state = checkStates.value(toBeModifiedChild->name()); + if (state != toBeModifiedChild->checked()) { + toBeModifiedChild->setChecked(state); + emit dataChanged(child, child, QVector() << Qt::CheckStateRole); + } + } else { // newly added (BAD: happens for renaming as well) + toBeModifiedChild->setChecked(Qt::Checked); + emit dataChanged(child, child, QVector() << Qt::CheckStateRole); + } + } +} + /***************************** Sort/Filter Model **********************************/ TestTreeSortFilterModel::TestTreeSortFilterModel(TestTreeModel *sourceModel, QObject *parent) diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 5ae83f0df77..81ad9418d98 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -37,6 +37,7 @@ namespace { namespace Autotest { namespace Internal { +struct TestCodeLocationAndType; class TestCodeParser; class TestInfo; class TestTreeItem; @@ -45,6 +46,11 @@ class TestTreeModel : public QAbstractItemModel { Q_OBJECT public: + enum Type { + AutoTest, + QuickTest + }; + static TestTreeModel* instance(); ~TestTreeModel(); @@ -62,18 +68,13 @@ public: bool hasTests() const; QList getAllTestCases() const; QList getSelectedTests() const; - TestTreeItem *unnamedQuickTests() const; + QString getMainFileForUnnamedQuickTest(const QString &qmlFile) const; + void qmlFilesAndFunctionNamesForMainFile(const QString &mainFile, QSet *filePaths, + QList *functionNames) const; + QList getUnnamedQuickTestFunctions() const; + QSet qmlFilesForProFile(const QString &proFile) const; + bool hasUnnamedQuickTests() const; - void modifyAutoTestSubtree(int row, TestTreeItem *newItem); - void removeAutoTestSubtreeByFilePath(const QString &file); - void addAutoTest(TestTreeItem *newItem); - void removeAllAutoTests(); - - void modifyQuickTestSubtree(int row, TestTreeItem *newItem); - void removeQuickTestSubtreeByFilePath(const QString &file); - void addQuickTest(TestTreeItem *newItem); - void removeAllQuickTests(); - bool removeUnnamedQuickTests(const QString &filePath); signals: void testTreeModelChanged(); @@ -81,8 +82,23 @@ signals: public slots: private: + void addTestTreeItem(const TestTreeItem &item, Type type); + void addTestTreeItems(const QList &itemList, Type type); + void updateUnnamedQuickTest(const QString &fileName, const QString &mainFile, + const QMap &functions); + void modifyTestTreeItem(TestTreeItem item, Type type, const QString &file); + void removeAllTestItems(); + void removeTestTreeItems(const QString &filePath, Type type); + void removeUnnamedQuickTests(const QString &filePath); + + TestTreeItem *unnamedQuickTests() const; + TestTreeItem *rootItemForType(Type type); + QModelIndex rootIndexForType(Type type); + explicit TestTreeModel(QObject *parent = 0); - void modifyTestSubtree(QModelIndex &toBeModifiedIndex, TestTreeItem *newItem); + void modifyTestSubtree(QModelIndex &toBeModifiedIndex, const TestTreeItem &newItem); + void processChildren(QModelIndex &parentIndex, const TestTreeItem &newItem, + const int upperBound, const QHash &checkStates); TestTreeItem *m_rootItem; TestTreeItem *m_autoTestRootItem; diff --git a/plugins/autotest/testvisitor.h b/plugins/autotest/testvisitor.h index bba9f0ebdae..ae6b844ca2b 100644 --- a/plugins/autotest/testvisitor.h +++ b/plugins/autotest/testvisitor.h @@ -35,13 +35,6 @@ namespace Autotest { namespace Internal { -struct TestCodeLocationAndType { - QString m_fileName; - unsigned m_line; - unsigned m_column; - TestTreeItem::Type m_type; -}; - class TestVisitor : public CPlusPlus::SymbolVisitor { public: From 751d2e2bb1f0f2829fff8dac15b534fbadc25b3c Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 16 Feb 2015 12:18:02 +0100 Subject: [PATCH 061/200] Fix re-parsing of tests... ...for code split up into header and source. Change-Id: I8f1bf01e6ff6f88afc1e054318cd384b5f231eb6 Reviewed-by: Andre Poenitz --- plugins/autotest/testcodeparser.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 510ce09de29..a33a6cac9bb 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -372,19 +372,19 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr document) TestTreeItem item = constructTestTreeItem(declaringDoc->fileName(), QString(), testCaseName, line, column, testFunctions); updateModelAndCppDocMap(document, declaringDoc->fileName(), item); - } else { - // could not find the class to test, but QTest is included and QT_TESTLIB_LIB defined - // maybe file is only a referenced file - if (m_cppDocMap.contains(fileName)) { - const TestInfo info = m_cppDocMap[fileName]; - CPlusPlus::Snapshot snapshot = modelManager->snapshot(); - if (snapshot.contains(info.referencingFile())) { - checkDocumentForTestCode(snapshot.find(info.referencingFile()).value()); - } else { // no referencing file too, so this test case is no more a test case - m_cppDocMap.remove(fileName); - emit testItemsRemoved(fileName, TestTreeModel::AutoTest); - } - } + return; + } + } + // could not find the class to test, or QTest is not included and QT_TESTLIB_LIB defined + // maybe file is only a referenced file + if (m_cppDocMap.contains(fileName)) { + const TestInfo info = m_cppDocMap[fileName]; + CPlusPlus::Snapshot snapshot = modelManager->snapshot(); + if (snapshot.contains(info.referencingFile())) { + checkDocumentForTestCode(snapshot.find(info.referencingFile()).value()); + } else { // no referencing file too, so this test case is no more a test case + m_cppDocMap.remove(fileName); + emit testItemsRemoved(fileName, TestTreeModel::AutoTest); } } } From 213a687f454682b8cd1e79fc27762ac6f374502e Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 10 Feb 2015 14:20:43 +0100 Subject: [PATCH 062/200] Rework parsing and provide unit test Handling of parsing has slightly changed. The parser now uses simple states to be capable of postponing triggered parses if there is already a parsing in progress. Furthermore the parser now waits for the current project to be completely scanned. Change-Id: I6d4968d28194ba8d23d3a0ee6ab454d81a549e67 Reviewed-by: Andre Poenitz --- plugins/autotest/autotest.pro | 5 + plugins/autotest/autotestplugin.cpp | 12 ++ plugins/autotest/autotestplugin.h | 1 + plugins/autotest/autotestunittests.cpp | 123 +++++++++++++++ plugins/autotest/autotestunittests.h | 55 +++++++ plugins/autotest/autotestunittests.qrc | 32 ++++ plugins/autotest/testcodeparser.cpp | 144 ++++++++++++++++-- plugins/autotest/testcodeparser.h | 20 +++ plugins/autotest/testtreemodel.cpp | 23 ++- plugins/autotest/testtreemodel.h | 5 + .../unit_test/mixed_atp/mixed_atp.pro | 5 + .../autotest/unit_test/mixed_atp/src/main.cpp | 8 + .../autotest/unit_test/mixed_atp/src/src.pro | 6 + .../unit_test/mixed_atp/tests/auto/auto.pro | 15 ++ .../mixed_atp/tests/auto/bench/bench.pro | 12 ++ .../tests/auto/bench/tst_benchtest.cpp | 63 ++++++++ .../mixed_atp/tests/auto/dummy/dummy.pro | 10 ++ .../mixed_atp/tests/auto/dummy/tst_foo.cpp | 82 ++++++++++ .../mixed_atp/tests/auto/dummy/tst_foo.h | 43 ++++++ .../mixed_atp/tests/auto/gui/gui.pro | 8 + .../mixed_atp/tests/auto/gui/tst_guitest.cpp | 89 +++++++++++ .../tests/auto/quickauto/TestDummy.qml | 10 ++ .../tests/auto/quickauto/bar/tst_foo.qml | 29 ++++ .../mixed_atp/tests/auto/quickauto/main.cpp | 3 + .../auto/quickauto/notlisted/tst_bla.qml | 29 ++++ .../tests/auto/quickauto/quickauto.pro | 14 ++ .../tests/auto/quickauto/tst_test1.qml | 33 ++++ .../tests/auto/quickauto/tst_test2.qml | 47 ++++++ .../tests/auto/quickauto/tst_test3.qml | 30 ++++ .../mixed_atp/tests/auto/quickauto2/main.cpp | 3 + .../tests/auto/quickauto2/quickauto2.pro | 11 ++ .../tests/auto/quickauto2/tst_test1.qml | 33 ++++ .../tests/auto/quickauto2/tst_test2.qml | 33 ++++ .../unit_test/mixed_atp/tests/tests.pro | 4 + plugins/autotest/unit_test/plain/plain.pro | 4 + .../unit_test/plain/test_plain/test_plain.pro | 13 ++ .../unit_test/plain/test_plain/tst_simple.cpp | 65 ++++++++ .../unit_test/plain/test_plain/tst_simple.h | 4 + 38 files changed, 1108 insertions(+), 18 deletions(-) create mode 100644 plugins/autotest/autotestunittests.cpp create mode 100644 plugins/autotest/autotestunittests.h create mode 100644 plugins/autotest/autotestunittests.qrc create mode 100644 plugins/autotest/unit_test/mixed_atp/mixed_atp.pro create mode 100644 plugins/autotest/unit_test/mixed_atp/src/main.cpp create mode 100644 plugins/autotest/unit_test/mixed_atp/src/src.pro create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/auto.pro create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.pro create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.pro create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.pro create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/TestDummy.qml create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/main.cpp create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.pro create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/main.cpp create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.pro create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/tests.pro create mode 100644 plugins/autotest/unit_test/plain/plain.pro create mode 100644 plugins/autotest/unit_test/plain/test_plain/test_plain.pro create mode 100644 plugins/autotest/unit_test/plain/test_plain/tst_simple.cpp create mode 100644 plugins/autotest/unit_test/plain/test_plain/tst_simple.h diff --git a/plugins/autotest/autotest.pro b/plugins/autotest/autotest.pro index ecc89345754..4d3c6643f29 100644 --- a/plugins/autotest/autotest.pro +++ b/plugins/autotest/autotest.pro @@ -56,3 +56,8 @@ RESOURCES += \ FORMS += \ testsettingspage.ui +equals(TEST, 1) { + HEADERS += autotestunittests.h + SOURCES += autotestunittests.cpp + RESOURCES += autotestunittests.qrc +} diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index 624812200ce..46e2a311d9a 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -44,6 +44,10 @@ #include +#ifdef WITH_TESTS +#include "autotestunittests.h" +#endif + using namespace Autotest::Internal; static AutotestPlugin *m_instance = 0; @@ -151,3 +155,11 @@ void AutotestPlugin::triggerAction() tr("This is an action from Autotest.")); } +QList AutotestPlugin::createTestObjects() const +{ + QList tests; +#ifdef WITH_TESTS + tests << new AutoTestUnitTests(TestTreeModel::instance()); +#endif + return tests; +} diff --git a/plugins/autotest/autotestplugin.h b/plugins/autotest/autotestplugin.h index be4a8037171..af5fcc91db9 100644 --- a/plugins/autotest/autotestplugin.h +++ b/plugins/autotest/autotestplugin.h @@ -52,6 +52,7 @@ private slots: private: bool checkLicense(); void initializeMenuEntries(); + QList createTestObjects() const; const QSharedPointer m_settings; }; diff --git a/plugins/autotest/autotestunittests.cpp b/plugins/autotest/autotestunittests.cpp new file mode 100644 index 00000000000..50556d7e003 --- /dev/null +++ b/plugins/autotest/autotestunittests.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "autotestconstants.h" +#include "autotestunittests.h" +#include "testcodeparser.h" +#include "testtreemodel.h" + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +using namespace Core; +using namespace ProjectExplorer; +using namespace Utils; + +namespace Autotest { +namespace Internal { + +AutoTestUnitTests::AutoTestUnitTests(TestTreeModel *model, QObject *parent) + : QObject(parent), + m_model(model), + m_tmpDir(0), + m_isQt4(false) +{ +} + +void AutoTestUnitTests::initTestCase() +{ + const QList allKits = KitManager::kits(); + if (allKits.count() != 1) + QSKIP("This test requires exactly one kit to be present"); + if (auto qtVersion = QtSupport::QtKitInformation::qtVersion(allKits.first())) + m_isQt4 = qtVersion->qtVersionString().startsWith(QLatin1Char('4')); + else + QSKIP("Could not figure out which Qt version is used for default kit."); + const ToolChain * const toolchain = ToolChainKitInformation::toolChain(allKits.first()); + if (!toolchain) + QSKIP("This test requires that there is a kit with a toolchain."); + + m_tmpDir = new CppTools::Tests::TemporaryCopiedDir(QLatin1String(":/unit_test")); +} + +void AutoTestUnitTests::cleanupTestCase() +{ + delete m_tmpDir; +} + +void AutoTestUnitTests::testCodeParser() +{ + QFETCH(QString, projectFilePath); + QFETCH(int, expectedAutoTestsCount); + QFETCH(int, expectedNamedQuickTestsCount); + QFETCH(int, expectedUnnamedQuickTestsCount); + + NavigationWidget *navigation = NavigationWidget::instance(); + navigation->activateSubWidget(Constants::AUTOTEST_ID); + + CppTools::Tests::ProjectOpenerAndCloser projectManager; + const CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true); + QVERIFY(projectInfo.isValid()); + + QSignalSpy parserSpy(m_model->parser(), SIGNAL(parsingFinished())); + QVERIFY(parserSpy.wait(20000)); + + if (m_isQt4) + expectedNamedQuickTestsCount = expectedUnnamedQuickTestsCount = 0; + + QCOMPARE(m_model->autoTestsCount(), expectedAutoTestsCount); + QCOMPARE(m_model->namedQuickTestsCount(), expectedNamedQuickTestsCount); + QCOMPARE(m_model->unnamedQuickTestsCount(), expectedUnnamedQuickTestsCount); + + QCOMPARE(m_model->parser()->autoTestsCount(), expectedAutoTestsCount); + QCOMPARE(m_model->parser()->namedQuickTestsCount(), expectedNamedQuickTestsCount); + QCOMPARE(m_model->parser()->unnamedQuickTestsCount(), expectedUnnamedQuickTestsCount); + +} + +void AutoTestUnitTests::testCodeParser_data() +{ + QTest::addColumn("projectFilePath"); + QTest::addColumn("expectedAutoTestsCount"); + QTest::addColumn("expectedNamedQuickTestsCount"); + QTest::addColumn("expectedUnnamedQuickTestsCount"); + + + QTest::newRow("plainAutoTest") + << QString(m_tmpDir->path() + QLatin1String("/plain/plain.pro")) + << 1 << 0 << 0; + QTest::newRow("mixedAutoTestAndQuickTests") + << QString(m_tmpDir->path() + QLatin1String("/mixed_atp/mixed_atp.pro")) + << 3 << 5 << 3; +} + +} // namespace Internal +} // namespace Autotest diff --git a/plugins/autotest/autotestunittests.h b/plugins/autotest/autotestunittests.h new file mode 100644 index 00000000000..16c6042b5dc --- /dev/null +++ b/plugins/autotest/autotestunittests.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef AUTOTESTUNITTESTS_H +#define AUTOTESTUNITTESTS_H + +#include +#include + +namespace CppTools { namespace Tests { class TemporaryCopiedDir; } } + +namespace Autotest { +namespace Internal { + +class TestTreeModel; + +class AutoTestUnitTests : public QObject +{ + Q_OBJECT +public: + explicit AutoTestUnitTests(TestTreeModel *model, QObject *parent = 0); + +signals: + +private slots: + void initTestCase(); + void cleanupTestCase(); + void testCodeParser(); + void testCodeParser_data(); + +private: + TestTreeModel *m_model; + CppTools::Tests::TemporaryCopiedDir *m_tmpDir; + bool m_isQt4; +}; + +} // namespace Internal +} // namespace Autotest + +#endif // AUTOTESTUNITTESTS_H diff --git a/plugins/autotest/autotestunittests.qrc b/plugins/autotest/autotestunittests.qrc new file mode 100644 index 00000000000..6fb5348e544 --- /dev/null +++ b/plugins/autotest/autotestunittests.qrc @@ -0,0 +1,32 @@ + + + unit_test/mixed_atp/src/main.cpp + unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp + unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp + unit_test/mixed_atp/tests/auto/dummy/tst_foo.h + unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp + unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml + unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml + unit_test/mixed_atp/tests/auto/quickauto/main.cpp + unit_test/mixed_atp/tests/auto/quickauto/TestDummy.qml + unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml + unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml + unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml + unit_test/mixed_atp/tests/auto/quickauto2/main.cpp + unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml + unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml + unit_test/plain/test_plain/tst_simple.cpp + unit_test/plain/test_plain/tst_simple.h + unit_test/plain/plain.pro + unit_test/mixed_atp/mixed_atp.pro + unit_test/plain/test_plain/test_plain.pro + unit_test/mixed_atp/tests/tests.pro + unit_test/mixed_atp/src/src.pro + unit_test/mixed_atp/tests/auto/bench/bench.pro + unit_test/mixed_atp/tests/auto/dummy/dummy.pro + unit_test/mixed_atp/tests/auto/gui/gui.pro + unit_test/mixed_atp/tests/auto/quickauto/quickauto.pro + unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.pro + unit_test/mixed_atp/tests/auto/auto.pro + + diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index a33a6cac9bb..0f950d305bd 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -49,7 +49,10 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent) : QObject(parent), m_model(parent), m_parserEnabled(true), - m_pendingUpdate(false) + m_pendingUpdate(false), + m_fullUpdatePostPoned(false), + m_partialUpdatePostPoned(false), + m_parserState(Idle) { // connect to ProgressManager to post-pone test parsing when CppModelManager is parsing auto progressManager = qobject_cast(Core::ProgressManager::instance()); @@ -57,6 +60,8 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent) this, &TestCodeParser::onTaskStarted); connect(progressManager, &Core::ProgressManager::allTasksFinished, this, &TestCodeParser::onAllTasksFinished); + connect(this, &TestCodeParser::partialParsingFinished, + this, &TestCodeParser::onPartialParsingFinished); } TestCodeParser::~TestCodeParser() @@ -81,25 +86,26 @@ void TestCodeParser::updateTestTree() { if (!m_parserEnabled) { m_pendingUpdate = true; - qDebug() << "Skipped update due to running parser or pro file evaluate"; return; } - qDebug("updating TestTreeModel"); - - clearMaps(); - emit cacheCleared(); - if (ProjectExplorer::Project *project = currentProject()) { if (auto qmakeProject = qobject_cast(project)) { + if (qmakeProject->asyncUpdateState() != QmakeProjectManager::QmakeProject::Base) { + m_pendingUpdate = true; + return; + } connect(qmakeProject, &QmakeProjectManager::QmakeProject::proFilesEvaluated, this, &TestCodeParser::onProFileEvaluated, Qt::UniqueConnection); } } else return; - scanForTests(); m_pendingUpdate = false; + + clearMaps(); + emit cacheCleared(); + scanForTests(); } /****** scan for QTest related stuff helpers ******/ @@ -443,7 +449,7 @@ void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &docume } else if (!project->files(ProjectExplorer::Project::AllFiles).contains(fileName)) { return; } - checkDocumentForTestCode(document); + scanForTests(QStringList(fileName)); } void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) @@ -464,15 +470,17 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) const CPlusPlus::Snapshot snapshot = CppTools::CppModelManager::instance()->snapshot(); if (m_quickDocMap.contains(fileName) && snapshot.contains(m_quickDocMap[fileName].referencingFile())) { - checkDocumentForTestCode(snapshot.document(m_quickDocMap[fileName].referencingFile())); + if (!m_quickDocMap[fileName].referencingFile().isEmpty()) + scanForTests(QStringList(m_quickDocMap[fileName].referencingFile())); } if (!m_quickDocMap.contains(tr(Constants::UNNAMED_QUICKTESTS))) return; // special case of having unnamed TestCases const QString &mainFile = m_model->getMainFileForUnnamedQuickTest(fileName); - if (!mainFile.isEmpty() && snapshot.contains(mainFile)) - checkDocumentForTestCode(snapshot.document(mainFile)); + if (!mainFile.isEmpty() && snapshot.contains(mainFile)) { + scanForTests(QStringList(mainFile)); + } } void TestCodeParser::removeFiles(const QStringList &files) @@ -481,13 +489,62 @@ void TestCodeParser::removeFiles(const QStringList &files) removeTestsIfNecessary(file); } +bool TestCodeParser::postponed(const QStringList &fileList) +{ + switch (m_parserState) { + case Idle: + return false; + case PartialParse: + // partial is running, postponing a full parse + if (fileList.isEmpty()) { + m_partialUpdatePostPoned = false; + m_postPonedFiles.clear(); + m_fullUpdatePostPoned = true; + } else { + // partial parse triggered, but full parse is postponed already, ignoring this + if (m_fullUpdatePostPoned) + return true; + // partial parse triggered, postpone or add current files to already postponed partial + foreach (const QString &file, fileList) + m_postPonedFiles.insert(file); + m_partialUpdatePostPoned = true; + } + return true; + case FullParse: + // full parse is running, postponing another full parse + if (fileList.isEmpty()) { + m_partialUpdatePostPoned = false; + m_postPonedFiles.clear(); + m_fullUpdatePostPoned = true; + } else { + // full parse already postponed, ignoring triggering a partial parse + if (m_fullUpdatePostPoned) { + return true; + } + // partial parse triggered, postpone or add current files to already postponed partial + foreach (const QString &file, fileList) + m_postPonedFiles.insert(file); + m_partialUpdatePostPoned = true; + } + return true; + } + QTC_ASSERT(false, return false); // should not happen at all +} + void TestCodeParser::scanForTests(const QStringList &fileList) { + if (postponed(fileList)) + return; + QStringList list; if (fileList.isEmpty()) { list = currentProject()->files(ProjectExplorer::Project::AllFiles); + if (list.isEmpty()) + return; + m_parserState = FullParse; } else { list << fileList; + m_parserState = PartialParse; } CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); @@ -499,6 +556,18 @@ void TestCodeParser::scanForTests(const QStringList &fileList) checkDocumentForTestCode(doc); } } + switch (m_parserState) { + case PartialParse: + m_parserState = Idle; + emit partialParsingFinished(); + break; + case FullParse: + m_parserState = Idle; + emit parsingFinished(); + break; + case Idle: + break; + } } void TestCodeParser::clearMaps() @@ -588,22 +657,39 @@ void TestCodeParser::removeTestsIfNecessaryByProFile(const QString &proFile) void TestCodeParser::onTaskStarted(Core::Id type) { - if (type != CppTools::Constants::TASK_INDEX - && type != QmakeProjectManager::Constants::PROFILE_EVALUATE) + if (type != CppTools::Constants::TASK_INDEX) return; m_parserEnabled = false; } void TestCodeParser::onAllTasksFinished(Core::Id type) { - if (type != CppTools::Constants::TASK_INDEX - && type != QmakeProjectManager::Constants::PROFILE_EVALUATE) + // only CPP parsing is relevant as we trigger Qml parsing internally anyway + if (type != CppTools::Constants::TASK_INDEX) return; m_parserEnabled = true; if (m_pendingUpdate) updateTestTree(); } +void TestCodeParser::onPartialParsingFinished() +{ + QTC_ASSERT(m_fullUpdatePostPoned != m_partialUpdatePostPoned + || ((m_fullUpdatePostPoned || m_partialUpdatePostPoned) == false), + m_partialUpdatePostPoned = false;m_postPonedFiles.clear();); + if (m_fullUpdatePostPoned) { + m_fullUpdatePostPoned = false; + updateTestTree(); + } else if (m_partialUpdatePostPoned) { + m_partialUpdatePostPoned = false; + QStringList tmp; + foreach (const QString &file, m_postPonedFiles) + tmp << file; + m_postPonedFiles.clear(); + scanForTests(tmp); + } +} + void TestCodeParser::updateUnnamedQuickTests(const QString &fileName, const QString &mainFile, const QMap &functions) { @@ -710,5 +796,31 @@ void TestCodeParser::onProFileEvaluated() } } +#ifdef WITH_TESTS +int TestCodeParser::autoTestsCount() const +{ + int count = 0; + foreach (const QString &file, m_cppDocMap.keys()) { + if (m_cppDocMap.value(file).referencingFile().isEmpty()) + ++count; + } + return count; +} + +int TestCodeParser::namedQuickTestsCount() const +{ + if (m_quickDocMap.contains(tr(Constants::UNNAMED_QUICKTESTS))) + return m_quickDocMap.size() - 1; + return m_quickDocMap.size(); +} + +int TestCodeParser::unnamedQuickTestsCount() const +{ + if (m_quickDocMap.contains(tr(Constants::UNNAMED_QUICKTESTS))) + return m_quickDocMap.value(tr(Constants::UNNAMED_QUICKTESTS)).testFunctions().size(); + return 0; +} +#endif + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index e2f590cabf1..d846769b37d 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -43,9 +43,21 @@ class TestCodeParser : public QObject { Q_OBJECT public: + enum State { + Idle, + PartialParse, + FullParse + }; + explicit TestCodeParser(TestTreeModel *parent = 0); virtual ~TestCodeParser(); +#ifdef WITH_TESTS + int autoTestsCount() const; + int namedQuickTestsCount() const; + int unnamedQuickTestsCount() const; +#endif + signals: void cacheCleared(); void testItemCreated(const TestTreeItem &item, TestTreeModel::Type type); @@ -55,6 +67,8 @@ signals: void unnamedQuickTestsUpdated(const QString &filePath, const QString &mainFile, const QMap &functions); void unnamedQuickTestsRemoved(const QString &filePath); + void parsingFinished(); + void partialParsingFinished(); public slots: void emitUpdateTestTree(); @@ -68,6 +82,7 @@ public slots: void onProFileEvaluated(); private: + bool postponed(const QStringList &fileList); void scanForTests(const QStringList &fileList = QStringList()); void clearMaps(); void removeTestsIfNecessary(const QString &fileName); @@ -75,6 +90,7 @@ private: void onTaskStarted(Core::Id type); void onAllTasksFinished(Core::Id type); + void onPartialParsingFinished(); void updateUnnamedQuickTests(const QString &fileName, const QString &mainFile, const QMap &functions); void updateModelAndCppDocMap(CPlusPlus::Document::Ptr document, @@ -87,6 +103,10 @@ private: QMap m_quickDocMap; bool m_parserEnabled; bool m_pendingUpdate; + bool m_fullUpdatePostPoned; + bool m_partialUpdatePostPoned; + QSet m_postPonedFiles; + State m_parserState; }; } // namespace Internal diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index f2ea94d6260..bccabf898a7 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -61,8 +61,6 @@ TestTreeModel::TestTreeModel(QObject *parent) : connect(m_parser, &TestCodeParser::unnamedQuickTestsRemoved, this, &TestTreeModel::removeUnnamedQuickTests); - m_parser->updateTestTree(); - // CppTools::CppModelManagerInterface *cppMM = CppTools::CppModelManagerInterface::instance(); // if (cppMM) { // // replace later on by @@ -808,6 +806,27 @@ void TestTreeModel::processChildren(QModelIndex &parentIndex, const TestTreeItem } } +#ifdef WITH_TESTS +int TestTreeModel::autoTestsCount() const +{ + return m_autoTestRootItem ? m_autoTestRootItem->childCount() : 0; +} + +int TestTreeModel::namedQuickTestsCount() const +{ + return m_quickTestRootItem + ? m_quickTestRootItem->childCount() - (hasUnnamedQuickTests() ? 1 : 0) + : 0; +} + +int TestTreeModel::unnamedQuickTestsCount() const +{ + if (TestTreeItem *unnamed = unnamedQuickTests()) + return unnamed->childCount(); + return 0; +} +#endif + /***************************** Sort/Filter Model **********************************/ TestTreeSortFilterModel::TestTreeSortFilterModel(TestTreeModel *sourceModel, QObject *parent) diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 81ad9418d98..b21eafbb7f3 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -75,6 +75,11 @@ public: QSet qmlFilesForProFile(const QString &proFile) const; bool hasUnnamedQuickTests() const; +#ifdef WITH_TESTS + int autoTestsCount() const; + int namedQuickTestsCount() const; + int unnamedQuickTestsCount() const; +#endif signals: void testTreeModelChanged(); diff --git a/plugins/autotest/unit_test/mixed_atp/mixed_atp.pro b/plugins/autotest/unit_test/mixed_atp/mixed_atp.pro new file mode 100644 index 00000000000..068ea5a3a64 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/mixed_atp.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs + +SUBDIRS += src \ + tests + diff --git a/plugins/autotest/unit_test/mixed_atp/src/main.cpp b/plugins/autotest/unit_test/mixed_atp/src/main.cpp new file mode 100644 index 00000000000..e0c10bca029 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/src/main.cpp @@ -0,0 +1,8 @@ +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + return a.exec(); +} + diff --git a/plugins/autotest/unit_test/mixed_atp/src/src.pro b/plugins/autotest/unit_test/mixed_atp/src/src.pro new file mode 100644 index 00000000000..9e554af8b71 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/src/src.pro @@ -0,0 +1,6 @@ +QT += gui widgets + +TEMPLATE = app + +SOURCES += main.cpp + diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/auto.pro b/plugins/autotest/unit_test/mixed_atp/tests/auto/auto.pro new file mode 100644 index 00000000000..cb4dc9ec327 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/auto.pro @@ -0,0 +1,15 @@ +TEMPLATE = subdirs + +SUBDIRS = \ + bench \ + dummy \ + gui + +greaterThan(QT_MAJOR_VERSION, 4) { + message("enabling quick tests") + SUBDIRS += quickauto \ + quickauto2 +} else { + message("quick tests disabled") +} + diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.pro b/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.pro new file mode 100644 index 00000000000..87f391f41d7 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.pro @@ -0,0 +1,12 @@ +QT += testlib + +QT -= gui + +TARGET = tst_benchtest +CONFIG += console +CONFIG -= app_bundle + +TEMPLATE = app + +SOURCES += tst_benchtest.cpp +DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp b/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp new file mode 100644 index 00000000000..1d968a01470 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ +#include +#include + +class BenchTest : public QObject +{ + Q_OBJECT + +public: + BenchTest(); + +private Q_SLOTS: + void testCase1(); + void testCase1_data(); +}; + +BenchTest::BenchTest() +{ +} + +void BenchTest::testCase1() +{ + QFETCH(bool, localAware); + + QString str1 = QLatin1String("Hello World"); + QString str2 = QLatin1String("Hallo Welt"); + if (!localAware) { + QBENCHMARK { + str1 == str2; + } + } else { + QBENCHMARK { + str1.localeAwareCompare(str2) == 0; + } + } +} + +void BenchTest::testCase1_data() +{ + QTest::addColumn("localAware"); + QTest::newRow("localAware") << true; + QTest::newRow("simple") << false; +} + +QTEST_MAIN(BenchTest) + +#include "tst_benchtest.moc" diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.pro b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.pro new file mode 100644 index 00000000000..40e95bcc390 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.pro @@ -0,0 +1,10 @@ +QT += testlib +QT += gui +CONFIG += qt warn_on depend_includepath testcase +TEMPLATE = app + +TARGET = tst_FooBar + +HEADERS += tst_foo.h +SOURCES += tst_foo.cpp + diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp new file mode 100644 index 00000000000..9dc2c9ec3a4 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ +#include "tst_foo.h" +#include +#include +#include + +Foo::Foo() +{ +} + +Foo::~Foo() +{ +} + +void Foo::initTestCase() +{ +} + +void Foo::cleanupTestCase() +{ + QWARN("Warning!"); +} + +void Foo::test_caseZero() +{ + QCOMPARE(1, 2); +} + +void Foo::test_case1() +{ + qDebug() << "test_case1"; + QFETCH(int, val); + + QEXPECT_FAIL("test2", "2", Continue); + QCOMPARE(val, 1); + QEXPECT_FAIL("test1", "bla", Abort); + QCOMPARE(val, 2); + QVERIFY2(true, "Hallo"); +} + +void Foo::test_case1_data() +{ + QTest::addColumn("val"); + QTest::newRow("test1") << 1; + QTest::newRow("test2") << 2; + QTest::newRow("test3") << 3; + QTest::newRow("test4") << 4; +} + +void Foo::test_case2() +{ + QThread::sleep(1); + qDebug() << "test_case2 - all pass"; + QSKIP("Skip for now", SkipAll); + QCOMPARE(1 ,1); + QVERIFY(true); +} + +void Foo::test_case4() +{ + qDebug("äøæ"); + QSKIP("Skipping test_case4", SkipSingle); + QFAIL("bla"); +} + +QTEST_MAIN(Foo) diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h new file mode 100644 index 00000000000..29bb8f5f6e4 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ +#ifndef FOO_H_INCLUDED +#define FOO_H_INCLUDED + +#include + +class Foo : public QObject +{ + Q_OBJECT + +public: + Foo(); + ~Foo(); + +private slots: + void initTestCase(); + void cleanupTestCase(); + void test_case1(); + void test_case1_data(); + void test_caseZero(); + void test_case2(); +// void test_case3() {} + void test_case4(); + void test_case5() {} +}; + +#endif diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.pro b/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.pro new file mode 100644 index 00000000000..10f8f27eb84 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.pro @@ -0,0 +1,8 @@ +QT += testlib gui widgets + +TARGET = tst_guitest + +TEMPLATE = app + +SOURCES += tst_guitest.cpp +DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp b/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp new file mode 100644 index 00000000000..13d61ba1519 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ +#include +#include +#include +#include + +class GuiTest : public QObject +{ + Q_OBJECT + +public: + GuiTest(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + void testCase1(); + void testGui_data(); + void testGui(); +}; + +GuiTest::GuiTest() +{ +} + +void GuiTest::initTestCase() +{ +} + +void GuiTest::cleanupTestCase() +{ +} + +void GuiTest::testCase1() +{ + QLatin1String str("Hello World"); + QLineEdit lineEdit; + QTest::keyClicks(&lineEdit, str); + QCOMPARE(lineEdit.text(), str); +} + +void GuiTest::testGui() +{ + QFETCH(QTestEventList, events); + QFETCH(QString, expected); + QLineEdit lineEdit; + events.simulate(&lineEdit); + QCOMPARE(lineEdit.text(), expected); +} + +void GuiTest::testGui_data() +{ + QTest::addColumn("events"); + QTest::addColumn("expected"); + + QTestEventList list1; + list1.addKeyClick('a'); + QTest::newRow("char") << list1 << "a"; + + QTestEventList list2; + list2.addKeyClick('a'); + list2.addKeyClick(Qt::Key_Backspace); + QTest::newRow("there and back again") << list2 << ""; +} + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + GuiTest gt; + return QTest::qExec(>, argc, argv); +} + +#include "tst_guitest.moc" diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/TestDummy.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/TestDummy.qml new file mode 100644 index 00000000000..ae30c811438 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/TestDummy.qml @@ -0,0 +1,10 @@ +import QtQuick 2.0 +import QtTest 1.0 + +TestCase { + name: "HalloBallo" + function test_bla() { + verify(true, "verifying true"); + } +} + diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml new file mode 100644 index 00000000000..ff825cd9896 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml @@ -0,0 +1,29 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ +import QtQuick 2.0 +import QtTest 1.0 + +TestCase { + name: "subdirTC" + + function test_blabla() { + compare(1, 2, "Bla"); + } + +} + diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/main.cpp b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/main.cpp new file mode 100644 index 00000000000..16a331e4cc4 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/main.cpp @@ -0,0 +1,3 @@ +#include + +QUICK_TEST_MAIN(blob) diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml new file mode 100644 index 00000000000..325b7c49276 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml @@ -0,0 +1,29 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ +import QtQuick 2.0 +import QtTest 1.0 + +TestCase { + name: "notlisted" + + function test_blablabla() { + compare(1, 2, "Blubb"); + } + +} + diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.pro b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.pro new file mode 100644 index 00000000000..dfe495dc1c5 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.pro @@ -0,0 +1,14 @@ +TEMPLATE = app +TARGET = test_mal_qtquick + +CONFIG += warn_on qmltestcase + +DISTFILES += \ + tst_test1.qml \ + tst_test2.qml \ + TestDummy.qml \ + bar/tst_foo.qml \ + tst_test3.qml + +SOURCES += \ + main.cpp diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml new file mode 100644 index 00000000000..8bf1379dc9c --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml @@ -0,0 +1,33 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ +import QtQuick 2.0 +import QtTest 1.0 + +TestCase { + name: "Banana" + + function test_math() { + compare(5 + 5, 10, "verifying 5 + 5 = 10"); + compare(10 - 5, 5, "verifying 10 - 5 = 5"); + } + + function test_fail() { + verify(false, "verifying false"); + } +} + diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml new file mode 100644 index 00000000000..c9a7f5286b7 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ +import QtQuick 2.0 +import QtTest 1.0 + +TestCase { + function test_str() { + var bla = String(); + bla = bla.concat("Hallo", " ", "Welt"); + var blubb = String("Hallo Welt"); + compare(blubb, bla, "Comparing concat"); + verify(blubb == bla, "Comparing concat equality") + } + +// nested TestCases actually fail +// TestCase { +// name: "boo" + +// function test_boo() { +// verify(true); +// } + +// TestCase { +// name: "far" + +// function test_far() { +// verify(true); +// } +// } +// } +} + diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml new file mode 100644 index 00000000000..3575c6b3132 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml @@ -0,0 +1,30 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ +import QtQuick 2.0 +import QtTest 1.0 + +TestCase { + function test_bolle() { + verify(true, "verifying true"); + } + + function test_str() { + compare("hallo", "hallo"); + } +} + diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/main.cpp b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/main.cpp new file mode 100644 index 00000000000..e496b3eb656 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/main.cpp @@ -0,0 +1,3 @@ +#include + +QUICK_TEST_MAIN(blob2) diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.pro b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.pro new file mode 100644 index 00000000000..61c76d1562c --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.pro @@ -0,0 +1,11 @@ +TEMPLATE = app +TARGET = test_mal_qtquick + +CONFIG += warn_on qmltestcase + +DISTFILES += \ + tst_test1.qml \ + tst_test2.qml + +SOURCES += \ + main.cpp diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml new file mode 100644 index 00000000000..8bf1379dc9c --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml @@ -0,0 +1,33 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ +import QtQuick 2.0 +import QtTest 1.0 + +TestCase { + name: "Banana" + + function test_math() { + compare(5 + 5, 10, "verifying 5 + 5 = 10"); + compare(10 - 5, 5, "verifying 10 - 5 = 5"); + } + + function test_fail() { + verify(false, "verifying false"); + } +} + diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml new file mode 100644 index 00000000000..a72913a84ed --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml @@ -0,0 +1,33 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ +import QtQuick 2.0 +import QtTest 1.0 + +Rectangle { + TestCase { + name: "nestedTC" + + function test_str() { + var bla = String(); + bla = bla.concat("Hello", " ", "World"); + var blubb = String("Hello World"); + compare(blubb, bla, "Comparing concat"); + verify(blubb == bla, "Comparing concat equality") + } + } +} diff --git a/plugins/autotest/unit_test/mixed_atp/tests/tests.pro b/plugins/autotest/unit_test/mixed_atp/tests/tests.pro new file mode 100644 index 00000000000..f1633f70c95 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/tests.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs + +SUBDIRS += auto + diff --git a/plugins/autotest/unit_test/plain/plain.pro b/plugins/autotest/unit_test/plain/plain.pro new file mode 100644 index 00000000000..07cbd339227 --- /dev/null +++ b/plugins/autotest/unit_test/plain/plain.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs + +SUBDIRS += test_plain + diff --git a/plugins/autotest/unit_test/plain/test_plain/test_plain.pro b/plugins/autotest/unit_test/plain/test_plain/test_plain.pro new file mode 100644 index 00000000000..1e8994b34c5 --- /dev/null +++ b/plugins/autotest/unit_test/plain/test_plain/test_plain.pro @@ -0,0 +1,13 @@ +QT += testlib +QT += gui +CONFIG += qt warn_on depend_includepath testcase + +TEMPLATE = app + +SOURCES += \ + tst_simple.cpp + +HEADERS += \ + tst_simple.h + +TARGET = totallyDifferentName diff --git a/plugins/autotest/unit_test/plain/test_plain/tst_simple.cpp b/plugins/autotest/unit_test/plain/test_plain/tst_simple.cpp new file mode 100644 index 00000000000..785aa6a1c8a --- /dev/null +++ b/plugins/autotest/unit_test/plain/test_plain/tst_simple.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ +#include "tst_simple.h" +#include + +namespace Foo { +namespace Bar { + +class bla : public QObject +{ + Q_OBJECT + +public: + bla() {} + ~bla() {} + +private slots: + void tst_dummy() {} + +}; + +class anotherBla : public QObject +{ + Q_OBJECT + +private slots: + void init() {} + void cleanup() {} + + void tst_bla() {} + void test_foo() {} + void test_bar() {} + void tst_batz() {} + void test_hello() {} + void test_io() { qDebug("ä");} +}; + +} // namespace Foo +} // namespace Bar + +int main(int argc, char* argv[]) +{ + Foo::Bar::anotherBla *x2 = new Foo::Bar::anotherBla; + int result = QTest::qExec(x2, argc, argv); +// multiple QTest::qExec() calls actually do not work +// result += QTest::qExec(new Foo::Bar::bla, argc, argv); + return result; +} + +#include "tst_simple.moc" diff --git a/plugins/autotest/unit_test/plain/test_plain/tst_simple.h b/plugins/autotest/unit_test/plain/test_plain/tst_simple.h new file mode 100644 index 00000000000..25523237cb9 --- /dev/null +++ b/plugins/autotest/unit_test/plain/test_plain/tst_simple.h @@ -0,0 +1,4 @@ +#ifndef TST_SIMPLE_H +#define TST_SIMPLE_H +#include +#endif // TST_SIMPLE_H From 223b43e9e0d978e1c6c2afc5002489eef09ec9e4 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 12 Feb 2015 15:48:24 +0100 Subject: [PATCH 063/200] Enable and disable parser on demand The new approach enables the parser as soon the Tests navigation widget or the Tests results pane is visible. If none is displayed parsing will be disabled. This additionally fixes an issue of not parsing a project when having a project opened already before triggering the first Tests navigation widget to become visible. Change-Id: I7163268d405e07e85814097d65ff34790a98a3d1 Reviewed-by: Andre Poenitz --- plugins/autotest/testcodeparser.cpp | 15 +++++- plugins/autotest/testcodeparser.h | 4 +- plugins/autotest/testnavigationwidget.cpp | 27 +++------- plugins/autotest/testnavigationwidget.h | 1 + plugins/autotest/testresultspane.cpp | 22 ++++++-- plugins/autotest/testresultspane.h | 3 +- plugins/autotest/testtreemodel.cpp | 62 ++++++++++++++++++++++- plugins/autotest/testtreemodel.h | 4 ++ 8 files changed, 109 insertions(+), 29 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 0f950d305bd..2fc0fff3ca6 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -69,6 +69,15 @@ TestCodeParser::~TestCodeParser() clearMaps(); } +void TestCodeParser::setState(State state) +{ + m_parserState = state; + if (m_parserState == Disabled) { + m_pendingUpdate = m_fullUpdatePostPoned = m_partialUpdatePostPoned = false; + m_postPonedFiles.clear(); + } +} + void TestCodeParser::emitUpdateTestTree() { QTimer::singleShot(1000, this, SLOT(updateTestTree())); @@ -527,6 +536,9 @@ bool TestCodeParser::postponed(const QStringList &fileList) m_partialUpdatePostPoned = true; } return true; + case Disabled: + qWarning("Checking for postponing but being disabled..."); + return false; } QTC_ASSERT(false, return false); // should not happen at all } @@ -565,7 +577,8 @@ void TestCodeParser::scanForTests(const QStringList &fileList) m_parserState = Idle; emit parsingFinished(); break; - case Idle: + default: + qWarning("I should not be here..."); break; } } diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index d846769b37d..9b6670c320f 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -46,11 +46,13 @@ public: enum State { Idle, PartialParse, - FullParse + FullParse, + Disabled }; explicit TestCodeParser(TestTreeModel *parent = 0); virtual ~TestCodeParser(); + void setState(State state); #ifdef WITH_TESTS int autoTestsCount() const; diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index 0f1fca7a41e..83384556232 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -26,12 +26,8 @@ #include "testtreeitem.h" #include -#include -#include -#include #include #include -#include #include #include @@ -58,26 +54,14 @@ TestNavigationWidget::TestNavigationWidget(QWidget *parent) : layout->addWidget(Core::ItemViewFind::createSearchableWrapper(m_view)); setLayout(layout); - TestCodeParser *parser = m_model->parser(); - ProjectExplorer::SessionManager *sm = ProjectExplorer::SessionManager::instance(); - connect(sm, &ProjectExplorer::SessionManager::startupProjectChanged, - parser, &TestCodeParser::emitUpdateTestTree); - - CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); - connect(cppMM, &CppTools::CppModelManager::documentUpdated, - parser, &TestCodeParser::onCppDocumentUpdated, Qt::QueuedConnection); - connect(cppMM, &CppTools::CppModelManager::aboutToRemoveFiles, - parser, &TestCodeParser::removeFiles, Qt::QueuedConnection); - - QmlJS::ModelManagerInterface *qmlJsMM = QmlJSTools::Internal::ModelManager::instance(); - connect(qmlJsMM, &QmlJS::ModelManagerInterface::documentUpdated, - parser, &TestCodeParser::onQmlDocumentUpdated, Qt::QueuedConnection); - connect(qmlJsMM, &QmlJS::ModelManagerInterface::aboutToRemoveFiles, - parser, &TestCodeParser::removeFiles, Qt::QueuedConnection); - connect(m_view, &TestTreeView::activated, this, &TestNavigationWidget::onItemActivated); } +TestNavigationWidget::~TestNavigationWidget() +{ + m_model->disableParsing(); +} + void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event) { const bool enabled = !TestRunner::instance()->isTestRunning(); @@ -223,6 +207,7 @@ Core::NavigationView TestNavigationWidgetFactory::createWidget() Core::NavigationView view; view.widget = treeViewWidget; view.dockToolBarWidgets = treeViewWidget->createToolButtons(); + TestTreeModel::instance()->enableParsing(); return view; } diff --git a/plugins/autotest/testnavigationwidget.h b/plugins/autotest/testnavigationwidget.h index 2700cf2c125..50d6ae8970a 100644 --- a/plugins/autotest/testnavigationwidget.h +++ b/plugins/autotest/testnavigationwidget.h @@ -46,6 +46,7 @@ class TestNavigationWidget : public QWidget public: explicit TestNavigationWidget(QWidget *parent = 0); + ~TestNavigationWidget(); void contextMenuEvent(QContextMenuEvent *event); QList createToolButtons(); diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index f2430fd420b..cb93d156faa 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -42,7 +42,8 @@ namespace Internal { TestResultsPane::TestResultsPane(QObject *parent) : Core::IOutputPane(parent), - m_context(new Core::IContext(this)) + m_context(new Core::IContext(this)), + m_wasVisibleBefore(false) { m_outputWidget = new QWidget; QVBoxLayout *outputLayout = new QVBoxLayout; @@ -87,8 +88,6 @@ TestResultsPane::TestResultsPane(QObject *parent) : this, &TestResultsPane::onTestRunStarted); connect(TestRunner::instance(), &TestRunner::testRunFinished, this, &TestResultsPane::onTestRunFinished); - connect(TestTreeModel::instance(), &TestTreeModel::testTreeModelChanged, - this, &TestResultsPane::onTestTreeModelChanged); } void TestResultsPane::createToolButtons() @@ -178,8 +177,23 @@ void TestResultsPane::clearContents() m_summaryWidget->setVisible(false); } -void TestResultsPane::visibilityChanged(bool) +void TestResultsPane::visibilityChanged(bool visible) { + if (visible) { + if (m_wasVisibleBefore) + return; + connect(TestTreeModel::instance(), &TestTreeModel::testTreeModelChanged, + this, &TestResultsPane::onTestTreeModelChanged); + m_wasVisibleBefore = true; + TestTreeModel::instance()->enableParsing(); + } else { + if (!m_wasVisibleBefore) + return; + disconnect(TestTreeModel::instance(), &TestTreeModel::testTreeModelChanged, + this, &TestResultsPane::onTestTreeModelChanged); + m_wasVisibleBefore = false; + TestTreeModel::instance()->disableParsing(); + } } void TestResultsPane::setFocus() diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h index 99c35552362..3567bd292ec 100644 --- a/plugins/autotest/testresultspane.h +++ b/plugins/autotest/testresultspane.h @@ -58,7 +58,7 @@ public: QString displayName() const; int priorityInStatusBar() const; void clearContents(); - void visibilityChanged(bool); + void visibilityChanged(bool visible); void setFocus(); bool hasFocus() const; bool canFocus() const; @@ -102,6 +102,7 @@ private: QToolButton *m_stopTestRun; QToolButton *m_filterButton; QMenu *m_filterMenu; + bool m_wasVisibleBefore; }; } // namespace Internal diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index bccabf898a7..cc54b6969ae 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -31,6 +31,8 @@ #include #include +#include + #include #include @@ -46,7 +48,9 @@ TestTreeModel::TestTreeModel(QObject *parent) : m_rootItem(new TestTreeItem(QString(), QString(), TestTreeItem::ROOT)), m_autoTestRootItem(new TestTreeItem(tr("Auto Tests"), QString(), TestTreeItem::ROOT, m_rootItem)), m_quickTestRootItem(new TestTreeItem(tr("Qt Quick Tests"), QString(), TestTreeItem::ROOT, m_rootItem)), - m_parser(new TestCodeParser(this)) + m_parser(new TestCodeParser(this)), + m_connectionsInitialized(false), + m_initializationCounter(0) { m_rootItem->appendChild(m_autoTestRootItem); m_rootItem->appendChild(m_quickTestRootItem); @@ -90,6 +94,62 @@ TestTreeModel::~TestTreeModel() m_instance = 0; } +void TestTreeModel::enableParsing() +{ + ++m_initializationCounter; + + if (m_connectionsInitialized) + return; + + m_parser->setState(TestCodeParser::Idle); + + ProjectExplorer::SessionManager *sm = ProjectExplorer::SessionManager::instance(); + connect(sm, &ProjectExplorer::SessionManager::startupProjectChanged, + m_parser, &TestCodeParser::emitUpdateTestTree); + + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + connect(cppMM, &CppTools::CppModelManager::documentUpdated, + m_parser, &TestCodeParser::onCppDocumentUpdated, Qt::QueuedConnection); + connect(cppMM, &CppTools::CppModelManager::aboutToRemoveFiles, + m_parser, &TestCodeParser::removeFiles, Qt::QueuedConnection); + + QmlJS::ModelManagerInterface *qmlJsMM = QmlJS::ModelManagerInterface::instance(); + connect(qmlJsMM, &QmlJS::ModelManagerInterface::documentUpdated, + m_parser, &TestCodeParser::onQmlDocumentUpdated, Qt::QueuedConnection); + connect(qmlJsMM, &QmlJS::ModelManagerInterface::aboutToRemoveFiles, + m_parser, &TestCodeParser::removeFiles, Qt::QueuedConnection); + m_connectionsInitialized = true; + m_parser->updateTestTree(); +} + +void TestTreeModel::disableParsing() +{ + if (!m_connectionsInitialized) + return; + if (--m_initializationCounter != 0) + return; + + ProjectExplorer::SessionManager *sm = ProjectExplorer::SessionManager::instance(); + disconnect(sm, &ProjectExplorer::SessionManager::startupProjectChanged, + m_parser, &TestCodeParser::emitUpdateTestTree); + + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + disconnect(cppMM, &CppTools::CppModelManager::documentUpdated, + m_parser, &TestCodeParser::onCppDocumentUpdated); + disconnect(cppMM, &CppTools::CppModelManager::aboutToRemoveFiles, + m_parser, &TestCodeParser::removeFiles); + + QmlJS::ModelManagerInterface *qmlJsMM = QmlJS::ModelManagerInterface::instance(); + disconnect(qmlJsMM, &QmlJS::ModelManagerInterface::documentUpdated, + m_parser, &TestCodeParser::onQmlDocumentUpdated); + disconnect(qmlJsMM, &QmlJS::ModelManagerInterface::aboutToRemoveFiles, + m_parser, &TestCodeParser::removeFiles); + + m_parser->setState(TestCodeParser::Disabled); + + m_connectionsInitialized = false; +} + QModelIndex TestTreeModel::index(int row, int column, const QModelIndex &parent) const { if (!hasIndex(row, column, parent)) diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index b21eafbb7f3..46a7b28a956 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -53,6 +53,8 @@ public: static TestTreeModel* instance(); ~TestTreeModel(); + void enableParsing(); + void disableParsing(); QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; QModelIndex parent(const QModelIndex &index) const; @@ -109,6 +111,8 @@ private: TestTreeItem *m_autoTestRootItem; TestTreeItem *m_quickTestRootItem; TestCodeParser *m_parser; + bool m_connectionsInitialized; + int m_initializationCounter; }; From 4caba7a3dda9a22a505d96799233dc35de29dba3 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 13 Feb 2015 15:44:18 +0100 Subject: [PATCH 064/200] Perform parsing asynchronously... ...to avoid blocking the ui thread. Parsing will now performed in a separate thread, except for small changes where this would create too much overhead. Change-Id: I1db441594f1684f969bb86c9423c0fb0bcb1a53a Reviewed-by: Andre Poenitz --- plugins/autotest/autotestconstants.h | 1 + plugins/autotest/autotestplugin.cpp | 6 +- plugins/autotest/testcodeparser.cpp | 174 +++++++++++++++++---------- plugins/autotest/testcodeparser.h | 6 +- plugins/autotest/testinfo.cpp | 6 + plugins/autotest/testinfo.h | 16 +++ plugins/autotest/testtreeitem.h | 7 +- plugins/autotest/testtreemodel.cpp | 19 +-- plugins/autotest/testtreemodel.h | 2 + 9 files changed, 166 insertions(+), 71 deletions(-) diff --git a/plugins/autotest/autotestconstants.h b/plugins/autotest/autotestconstants.h index fc254e42283..c82c5efbca2 100644 --- a/plugins/autotest/autotestconstants.h +++ b/plugins/autotest/autotestconstants.h @@ -29,6 +29,7 @@ const char MENU_ID[] = "AutoTest.Menu"; const char AUTOTEST_ID[] = "AutoTest.ATP"; const char AUTOTEST_CONTEXT[] = "Auto Tests"; const char TASK_INDEX[] = "AutoTest.Task.Index"; +const char TASK_PARSE[] = "AutoTest.Task.Parse"; const char UNNAMED_QUICKTESTS[] = QT_TR_NOOP(""); const char AUTOTEST_SETTINGS_CATEGORY[] = "ZY.Tests"; diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index 46e2a311d9a..0d6f7be04ff 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -21,6 +21,7 @@ #include "testrunner.h" #include "testsettings.h" #include "testsettingspage.h" +#include "testtreeitem.h" #include "testtreeview.h" #include "testtreemodel.h" #include "testresultspane.h" @@ -57,7 +58,10 @@ AutotestPlugin::AutotestPlugin() { // needed to be used in QueuedConnection connects qRegisterMetaType(); - // Create your members + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + m_instance = this; } diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 2fc0fff3ca6..0a9b8b6893a 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -21,6 +21,7 @@ #include "testinfo.h" #include "testvisitor.h" +#include #include #include @@ -39,9 +40,13 @@ #include #include +#include #include #include +#include +#include + namespace Autotest { namespace Internal { @@ -66,7 +71,7 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent) TestCodeParser::~TestCodeParser() { - clearMaps(); + clearCache(); } void TestCodeParser::setState(State state) @@ -112,7 +117,7 @@ void TestCodeParser::updateTestTree() m_pendingUpdate = false; - clearMaps(); + clearCache(); emit cacheCleared(); scanForTests(); } @@ -353,6 +358,26 @@ static TestTreeItem constructTestTreeItem(const QString &fileName, /****** end of helpers ******/ +void performParse(QFutureInterface &futureInterface, QStringList list, + TestCodeParser *testCodeParser) +{ + int progressValue = 0; + futureInterface.setProgressRange(0, list.size()); + futureInterface.setProgressValue(progressValue); + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + CPlusPlus::Snapshot snapshot = cppMM->snapshot(); + + foreach (const QString &file, list) { + if (snapshot.contains(file)) { + CPlusPlus::Document::Ptr doc = snapshot.find(file).value(); + futureInterface.setProgressValue(++progressValue); + testCodeParser->checkDocumentForTestCode(doc); + } + } + futureInterface.setProgressValue(list.size()); +} + +/****** threaded parsing stuff *******/ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr document) { const QString fileName = document->fileName(); @@ -445,6 +470,14 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr document) void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document) { + if (!m_parserEnabled) { + if (!m_pendingUpdate) { + m_partialUpdatePostPoned = true; + m_postPonedFiles.insert(document->fileName()); + } + return; + } + ProjectExplorer::Project *project = currentProject(); if (!project) return; @@ -463,6 +496,14 @@ void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &docume void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) { + if (!m_parserEnabled) { + if (!m_pendingUpdate) { + m_partialUpdatePostPoned = true; + m_postPonedFiles.insert(document->fileName()); + } + return; + } + ProjectExplorer::Project *project = currentProject(); if (!project) return; @@ -482,7 +523,7 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) if (!m_quickDocMap[fileName].referencingFile().isEmpty()) scanForTests(QStringList(m_quickDocMap[fileName].referencingFile())); } - if (!m_quickDocMap.contains(tr(Constants::UNNAMED_QUICKTESTS))) + if (m_unnamedQuickDocList.size() == 0) return; // special case of having unnamed TestCases @@ -548,8 +589,10 @@ void TestCodeParser::scanForTests(const QStringList &fileList) if (postponed(fileList)) return; + bool isFullParse = fileList.isEmpty(); + bool isSmallChange = !isFullParse && fileList.size() < 6; QStringList list; - if (fileList.isEmpty()) { + if (isFullParse) { list = currentProject()->files(ProjectExplorer::Project::AllFiles); if (list.isEmpty()) return; @@ -559,34 +602,33 @@ void TestCodeParser::scanForTests(const QStringList &fileList) m_parserState = PartialParse; } - CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); - CPlusPlus::Snapshot snapshot = cppMM->snapshot(); - - foreach (const QString &file, list) { - if (snapshot.contains(file)) { - CPlusPlus::Document::Ptr doc = snapshot.find(file).value(); - checkDocumentForTestCode(doc); + if (isSmallChange) { // no need to do this async or should we do this always async? + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + CPlusPlus::Snapshot snapshot = cppMM->snapshot(); + foreach (const QString &file, list) { + if (snapshot.contains(file)) { + CPlusPlus::Document::Ptr doc = snapshot.find(file).value(); + checkDocumentForTestCode(doc); + } } + emit onFinished(); + return; } - switch (m_parserState) { - case PartialParse: - m_parserState = Idle; - emit partialParsingFinished(); - break; - case FullParse: - m_parserState = Idle; - emit parsingFinished(); - break; - default: - qWarning("I should not be here..."); - break; - } + + QFuture future = QtConcurrent::run(&performParse, list, this); + Core::FutureProgress *progress + = Core::ProgressManager::addTask(future, isFullParse ? tr("Scanning for Tests") + : tr("Updating Tests"), + Autotest::Constants::TASK_PARSE); + connect(progress, &Core::FutureProgress::finished, + this, &TestCodeParser::onFinished); } -void TestCodeParser::clearMaps() +void TestCodeParser::clearCache() { m_cppDocMap.clear(); m_quickDocMap.clear(); + m_unnamedQuickDocList.clear(); } void TestCodeParser::removeTestsIfNecessary(const QString &fileName) @@ -611,24 +653,14 @@ void TestCodeParser::removeTestsIfNecessary(const QString &fileName) emit testItemsRemoved(file, TestTreeModel::QuickTest); } // unnamed Quick Tests must be handled separately + removeUnnamedQuickTestsByName(fileName); + QSet filePaths; QList functionNames; if (m_model->hasUnnamedQuickTests()) { m_model->qmlFilesAndFunctionNamesForMainFile(fileName, &filePaths, &functionNames); foreach (const QString &file, filePaths) emit testItemsRemoved(file, TestTreeModel::QuickTest); - // update info map - TestInfo unnamedInfo = m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)]; - QStringList functions = unnamedInfo.testFunctions(); - foreach (const QString &func, functionNames) - functions.removeOne(func); - unnamedInfo.setTestFunctions(functions); - if (functions.size() == 0) - m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); - else - m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), unnamedInfo); - } else { - m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); } } } @@ -655,17 +687,10 @@ void TestCodeParser::removeTestsIfNecessaryByProFile(const QString &proFile) } // handle unnamed Quick Tests const QSet &filePaths = m_model->qmlFilesForProFile(proFile); - foreach (const QString &fileName, filePaths) + foreach (const QString &fileName, filePaths) { + removeUnnamedQuickTestsByName(fileName); emit unnamedQuickTestsRemoved(fileName); - // update info map - TestInfo unnamedInfo = m_quickDocMap.value(tr(Constants::UNNAMED_QUICKTESTS), - TestInfo(QString(), QStringList(), 666)); - - unnamedInfo.setTestFunctions(m_model->getUnnamedQuickTestFunctions()); - if (unnamedInfo.testFunctions().isEmpty()) - m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); - else - m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), unnamedInfo); + } } void TestCodeParser::onTaskStarted(Core::Id type) @@ -683,6 +708,31 @@ void TestCodeParser::onAllTasksFinished(Core::Id type) m_parserEnabled = true; if (m_pendingUpdate) updateTestTree(); + else if (m_partialUpdatePostPoned) { + m_partialUpdatePostPoned = false; + QStringList tmp; + foreach (const QString &file, m_postPonedFiles) + tmp << file; + m_postPonedFiles.clear(); + scanForTests(tmp); + } +} + +void TestCodeParser::onFinished() +{ + switch (m_parserState) { + case PartialParse: + m_parserState = Idle; + emit partialParsingFinished(); + break; + case FullParse: + m_parserState = Idle; + emit parsingFinished(); + break; + default: + qWarning("I should not be here..."); + break; + } } void TestCodeParser::onPartialParsingFinished() @@ -710,16 +760,13 @@ void TestCodeParser::updateUnnamedQuickTests(const QString &fileName, const QStr m_quickDocMap.remove(fileName); emit testItemsRemoved(fileName, TestTreeModel::QuickTest); - emit unnamedQuickTestsUpdated(fileName, mainFile, functions); - - if (m_model->hasUnnamedQuickTests()) { - TestInfo info = m_quickDocMap.value(tr(Constants::UNNAMED_QUICKTESTS), - TestInfo(QString(), QStringList(), 666)); - info.setTestFunctions(m_model->getUnnamedQuickTestFunctions()); - m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), info); - } else { - m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); + removeUnnamedQuickTestsByName(fileName); + foreach (const QString &functionName, functions.keys()) { + UnnamedQuickTestInfo info(functionName, fileName); + m_unnamedQuickDocList.append(info); } + + emit unnamedQuickTestsUpdated(fileName, mainFile, functions); } void TestCodeParser::updateModelAndCppDocMap(CPlusPlus::Document::Ptr document, @@ -779,6 +826,7 @@ void TestCodeParser::updateModelAndQuickDocMap(QmlJS::Document::Ptr document, m_quickDocMap.insert(fileName, testInfo); } else { // if it was formerly unnamed remove the respective items + removeUnnamedQuickTestsByName(fileName); emit unnamedQuickTestsRemoved(fileName); emit testItemCreated(testItem, TestTreeModel::QuickTest); @@ -789,6 +837,14 @@ void TestCodeParser::updateModelAndQuickDocMap(QmlJS::Document::Ptr document, } } +void TestCodeParser::removeUnnamedQuickTestsByName(const QString &fileName) +{ + for (int i = m_unnamedQuickDocList.size() - 1; i >= 0; --i) { + if (m_unnamedQuickDocList.at(i).fileName() == fileName) + m_unnamedQuickDocList.removeAt(i); + } +} + void TestCodeParser::onProFileEvaluated() { ProjectExplorer::Project *project = currentProject(); @@ -822,16 +878,12 @@ int TestCodeParser::autoTestsCount() const int TestCodeParser::namedQuickTestsCount() const { - if (m_quickDocMap.contains(tr(Constants::UNNAMED_QUICKTESTS))) - return m_quickDocMap.size() - 1; return m_quickDocMap.size(); } int TestCodeParser::unnamedQuickTestsCount() const { - if (m_quickDocMap.contains(tr(Constants::UNNAMED_QUICKTESTS))) - return m_quickDocMap.value(tr(Constants::UNNAMED_QUICKTESTS)).testFunctions().size(); - return 0; + return m_unnamedQuickDocList.size(); } #endif diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 9b6670c320f..f2bb6de13ef 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -38,6 +38,7 @@ namespace Internal { struct TestCodeLocationAndType; class TestInfo; +class UnnamedQuickTestInfo; class TestCodeParser : public QObject { @@ -86,12 +87,13 @@ public slots: private: bool postponed(const QStringList &fileList); void scanForTests(const QStringList &fileList = QStringList()); - void clearMaps(); + void clearCache(); void removeTestsIfNecessary(const QString &fileName); void removeTestsIfNecessaryByProFile(const QString &proFile); void onTaskStarted(Core::Id type); void onAllTasksFinished(Core::Id type); + void onFinished(); void onPartialParsingFinished(); void updateUnnamedQuickTests(const QString &fileName, const QString &mainFile, const QMap &functions); @@ -99,10 +101,12 @@ private: const QString &declaringFile, TestTreeItem &testItem); void updateModelAndQuickDocMap(QmlJS::Document::Ptr document, const QString &referencingFile, TestTreeItem &testItem); + void removeUnnamedQuickTestsByName(const QString &fileName); TestTreeModel *m_model; QMap m_cppDocMap; QMap m_quickDocMap; + QList m_unnamedQuickDocList; bool m_parserEnabled; bool m_pendingUpdate; bool m_fullUpdatePostPoned; diff --git a/plugins/autotest/testinfo.cpp b/plugins/autotest/testinfo.cpp index ad904e9a0f1..e3e13274f7c 100644 --- a/plugins/autotest/testinfo.cpp +++ b/plugins/autotest/testinfo.cpp @@ -35,5 +35,11 @@ TestInfo::~TestInfo() m_functions.clear(); } +UnnamedQuickTestInfo::UnnamedQuickTestInfo(const QString &function, const QString &fileName) + : m_function(function), + m_fileName(fileName) +{ +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testinfo.h b/plugins/autotest/testinfo.h index b974824f9e0..cadd57212f9 100644 --- a/plugins/autotest/testinfo.h +++ b/plugins/autotest/testinfo.h @@ -54,6 +54,22 @@ private: QString m_proFile; }; +class UnnamedQuickTestInfo { +public: + explicit UnnamedQuickTestInfo(const QString &function = QString(), + const QString& fileName = QString()); + ~UnnamedQuickTestInfo() {} + + const QString function() const { return m_function; } + void setFunction(const QString &function) { m_function = function; } + const QString fileName() const { return m_fileName; } + void setFileName(const QString &fileName) { m_fileName = fileName; } + +private: + QString m_function; + QString m_fileName; +}; + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index 25a49f3edf7..e1814db356f 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -21,6 +21,7 @@ #include #include +#include namespace Autotest { namespace Internal { @@ -37,7 +38,8 @@ public: TEST_SPECIALFUNCTION }; - TestTreeItem(const QString &name, const QString &filePath, Type type, TestTreeItem *parent = 0); + TestTreeItem(const QString &name = QString(), const QString &filePath = QString(), + Type type = ROOT, TestTreeItem *parent = 0); virtual ~TestTreeItem(); TestTreeItem(const TestTreeItem& other); @@ -90,4 +92,7 @@ struct TestCodeLocationAndType { } // namespace Internal } // namespace Autotest +Q_DECLARE_METATYPE(Autotest::Internal::TestTreeItem) +Q_DECLARE_METATYPE(Autotest::Internal::TestCodeLocationAndType) + #endif // TESTTREEITEM_H diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index cc54b6969ae..8b9de455ade 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -55,15 +55,20 @@ TestTreeModel::TestTreeModel(QObject *parent) : m_rootItem->appendChild(m_autoTestRootItem); m_rootItem->appendChild(m_quickTestRootItem); - connect(m_parser, &TestCodeParser::cacheCleared, this, &TestTreeModel::removeAllTestItems); - connect(m_parser, &TestCodeParser::testItemCreated, this, &TestTreeModel::addTestTreeItem); - connect(m_parser, &TestCodeParser::testItemsCreated, this, &TestTreeModel::addTestTreeItems); - connect(m_parser, &TestCodeParser::testItemModified, this, &TestTreeModel::modifyTestTreeItem); - connect(m_parser, &TestCodeParser::testItemsRemoved, this, &TestTreeModel::removeTestTreeItems); + connect(m_parser, &TestCodeParser::cacheCleared, this, + &TestTreeModel::removeAllTestItems, Qt::QueuedConnection); + connect(m_parser, &TestCodeParser::testItemCreated, + this, &TestTreeModel::addTestTreeItem, Qt::QueuedConnection); + connect(m_parser, &TestCodeParser::testItemsCreated, + this, &TestTreeModel::addTestTreeItems, Qt::QueuedConnection); + connect(m_parser, &TestCodeParser::testItemModified, + this, &TestTreeModel::modifyTestTreeItem, Qt::QueuedConnection); + connect(m_parser, &TestCodeParser::testItemsRemoved, + this, &TestTreeModel::removeTestTreeItems, Qt::QueuedConnection); connect(m_parser, &TestCodeParser::unnamedQuickTestsUpdated, - this, &TestTreeModel::updateUnnamedQuickTest); + this, &TestTreeModel::updateUnnamedQuickTest, Qt::QueuedConnection); connect(m_parser, &TestCodeParser::unnamedQuickTestsRemoved, - this, &TestTreeModel::removeUnnamedQuickTests); + this, &TestTreeModel::removeUnnamedQuickTests, Qt::QueuedConnection); // CppTools::CppModelManagerInterface *cppMM = CppTools::CppModelManagerInterface::instance(); // if (cppMM) { diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 46a7b28a956..44186285a9f 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -152,4 +152,6 @@ private: } // namespace Internal } // namespace Autotest +Q_DECLARE_METATYPE(Autotest::Internal::TestTreeModel::Type) + #endif // TESTTREEMODEL_H From b9a60137ad79ec49ffd671e509af4086a4482440 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 16 Feb 2015 13:17:53 +0100 Subject: [PATCH 065/200] Clean up plugin Change-Id: I695adb992f4d1f32f266f1628f2094e4bcc81485 Reviewed-by: Andre Poenitz --- autotest-qtcreator-plugin.pro => autotest.pro | 0 plugins/autotest/autotestplugin.cpp | 29 ++++--------------- plugins/autotest/autotestplugin.h | 4 --- plugins/autotest/autotestunittests.cpp | 1 - plugins/autotest/testcodeparser.cpp | 2 -- plugins/autotest/testrunner.cpp | 6 ++-- plugins/autotest/testtreemodel.cpp | 1 - 7 files changed, 8 insertions(+), 35 deletions(-) rename autotest-qtcreator-plugin.pro => autotest.pro (100%) diff --git a/autotest-qtcreator-plugin.pro b/autotest.pro similarity index 100% rename from autotest-qtcreator-plugin.pro rename to autotest.pro diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index 0d6f7be04ff..82e20e82c33 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -18,6 +18,7 @@ #include "autotestplugin.h" #include "autotestconstants.h" +#include "testcodeparser.h" #include "testrunner.h" #include "testsettings.h" #include "testsettingspage.h" @@ -67,7 +68,6 @@ AutotestPlugin::AutotestPlugin() AutotestPlugin::~AutotestPlugin() { - // Unregister objects from the plugin manager's object pool // Delete members TestTreeModel *model = TestTreeModel::instance(); delete model; @@ -100,11 +100,12 @@ bool AutotestPlugin::checkLicense() void AutotestPlugin::initializeMenuEntries() { - QAction *action = new QAction(tr("Autotest action"), this); + QAction *action = new QAction(tr("Re&scan Tests"), this); Core::Command *command = Core::ActionManager::registerAction(action, Constants::ACTION_ID, Core::Context(Core::Constants::C_GLOBAL)); - command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Meta+A"))); - connect(action, SIGNAL(triggered()), this, SLOT(triggerAction())); + command->setDefaultKeySequence(QKeySequence(tr("Alt+Shift+T,Alt+S"))); + connect(action, &QAction::triggered, + TestTreeModel::instance()->parser(), &TestCodeParser::updateTestTree); Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::MENU_ID); menu->menu()->setTitle(tr("Tests")); @@ -114,13 +115,6 @@ void AutotestPlugin::initializeMenuEntries() bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorString) { - // Register objects in the plugin manager's object pool - // Load settings - // Add actions to menus - // Connect to other plugins' signals - // In the initialize function, a plugin can be sure that the plugins it - // depends on have initialized their members. - Q_UNUSED(arguments) Q_UNUSED(errorString) @@ -139,26 +133,13 @@ bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorStri void AutotestPlugin::extensionsInitialized() { - // Retrieve objects from the plugin manager's object pool - // In the extensionsInitialized function, a plugin can be sure that all - // plugins that depend on it are completely initialized. } ExtensionSystem::IPlugin::ShutdownFlag AutotestPlugin::aboutToShutdown() { - // Save settings - // Disconnect from signals that are not needed during shutdown - // Hide UI (if you add UI that is not in the main window directly) return SynchronousShutdown; } -void AutotestPlugin::triggerAction() -{ - QMessageBox::information(Core::ICore::mainWindow(), - tr("Action triggered"), - tr("This is an action from Autotest.")); -} - QList AutotestPlugin::createTestObjects() const { QList tests; diff --git a/plugins/autotest/autotestplugin.h b/plugins/autotest/autotestplugin.h index af5fcc91db9..aab664bc2d4 100644 --- a/plugins/autotest/autotestplugin.h +++ b/plugins/autotest/autotestplugin.h @@ -45,10 +45,6 @@ public: void extensionsInitialized(); ShutdownFlag aboutToShutdown(); - -private slots: - void triggerAction(); - private: bool checkLicense(); void initializeMenuEntries(); diff --git a/plugins/autotest/autotestunittests.cpp b/plugins/autotest/autotestunittests.cpp index 50556d7e003..1010bbc1918 100644 --- a/plugins/autotest/autotestunittests.cpp +++ b/plugins/autotest/autotestunittests.cpp @@ -31,7 +31,6 @@ #include #include -#include #include diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 0a9b8b6893a..09c0db02921 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -485,7 +485,6 @@ void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &docume if (m_cppDocMap.contains(fileName)) { if (m_cppDocMap[fileName].revision() == document->revision() && m_cppDocMap[fileName].editorRevision() == document->editorRevision()) { - qDebug("Skipped due revision equality"); // added to verify if this ever happens.. return; } } else if (!project->files(ProjectExplorer::Project::AllFiles).contains(fileName)) { @@ -510,7 +509,6 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) const QString fileName = document->fileName(); if (m_quickDocMap.contains(fileName)) { if ((int)m_quickDocMap[fileName].editorRevision() == document->editorRevision()) { - qDebug("Skipped due revision equality (QML)"); // added to verify this ever happens.... return; } } else if (!project->files(ProjectExplorer::Project::AllFiles).contains(fileName)) { diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index af1b5e17032..185803fb020 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -23,8 +23,6 @@ #include "testsettings.h" #include "testxmloutputreader.h" -#include // REMOVE - #include #include @@ -106,7 +104,9 @@ void TestRunner::setSelectedTests(const QList &selected) m_selectedTests = selected; } -void performTestRun(QFutureInterface &futureInterface, const QList selectedTests, const int timeout, const QString metricsOption, TestRunner* testRunner) +void performTestRun(QFutureInterface &futureInterface, + const QList selectedTests, const int timeout, + const QString metricsOption, TestRunner* testRunner) { int testCaseCount = 0; foreach (const TestConfiguration *config, selectedTests) diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 8b9de455ade..66abadd96a0 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -801,7 +801,6 @@ QModelIndex TestTreeModel::rootIndexForType(TestTreeModel::Type type) } void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, const TestTreeItem &newItem) - { if (!toBeModifiedIndex.isValid()) return; From b5341a9a0394364fa2b167402bfc0e9fb6540287 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 17 Feb 2015 10:33:35 +0100 Subject: [PATCH 066/200] Try to guess run configuration if none is explicitly set Additionally provide a setting to not display warnings regarding using a guessed run configuration. Change-Id: Ia7647f55e5085ffc84044281c5107770cd30d504 Reviewed-by: Tobias Hunger --- plugins/autotest/testconfiguration.cpp | 8 +- plugins/autotest/testconfiguration.h | 4 +- plugins/autotest/testrunner.cpp | 17 +- plugins/autotest/testsettings.cpp | 8 +- plugins/autotest/testsettings.h | 1 + plugins/autotest/testsettingspage.cpp | 2 + plugins/autotest/testsettingspage.ui | 466 +++++++++++++------------ plugins/autotest/testtreemodel.cpp | 33 ++ 8 files changed, 309 insertions(+), 230 deletions(-) diff --git a/plugins/autotest/testconfiguration.cpp b/plugins/autotest/testconfiguration.cpp index 9589d68c027..a8ca3743349 100644 --- a/plugins/autotest/testconfiguration.cpp +++ b/plugins/autotest/testconfiguration.cpp @@ -30,7 +30,8 @@ TestConfiguration::TestConfiguration(const QString &testClass, const QStringList m_testCases(testCases), m_testCaseCount(testCaseCount), m_unnamedOnly(false), - m_project(0) + m_project(0), + m_guessedConfiguration(false) { if (testCases.size() != 0) { m_testCaseCount = testCases.size(); @@ -102,5 +103,10 @@ void TestConfiguration::setUnnamedOnly(bool unnamedOnly) m_unnamedOnly = unnamedOnly; } +void TestConfiguration::setGuessedConfiguration(bool guessed) +{ + m_guessedConfiguration = guessed; +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testconfiguration.h b/plugins/autotest/testconfiguration.h index 8d9235b512b..82fb874ca48 100644 --- a/plugins/autotest/testconfiguration.h +++ b/plugins/autotest/testconfiguration.h @@ -50,6 +50,7 @@ public: void setEnvironment(const Utils::Environment &env); void setProject(ProjectExplorer::Project *project); void setUnnamedOnly(bool unnamedOnly); + void setGuessedConfiguration(bool guessed); QString testClass() const { return m_testClass; } QStringList testCases() const { return m_testCases; } @@ -62,7 +63,7 @@ public: Utils::Environment environment() const { return m_environment; } ProjectExplorer::Project *project() const { return m_project; } bool unnamedOnly() const { return m_unnamedOnly; } - + bool guessedConfiguration() const { return m_guessedConfiguration; } signals: @@ -80,6 +81,7 @@ private: QString m_displayName; Utils::Environment m_environment; ProjectExplorer::Project *m_project; + bool m_guessedConfiguration; }; } // namespace Internal diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 185803fb020..150e72750d4 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -185,12 +185,17 @@ void performTestRun(QFutureInterface &futureInterface, void TestRunner::runTests() { + const QSharedPointer settings = AutotestPlugin::instance()->settings(); + const int timeout = settings->timeout; + const QString metricsOption = TestSettings::metricsTypeToOption(settings->metrics); + const bool displayRunConfigWarnings = !settings->omitRunConfigWarn; + // clear old log and output pane TestResultsPane::instance()->clearContents(); // handle faulty test configurations QList toBeRemoved; - foreach (TestConfiguration *config, m_selectedTests) + foreach (TestConfiguration *config, m_selectedTests) { if (!config->project()) { toBeRemoved.append(config); TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, @@ -198,6 +203,12 @@ void TestRunner::runTests() "This might be the case for a faulty environment or similar." ).arg(config->displayName()))); } + if (displayRunConfigWarnings && config->guessedConfiguration()) { + TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, + tr("*** Project's run configuration was guessed for '%1' ***\n" + "This might cause trouble during execution.").arg(config->displayName()))); + } + } foreach (TestConfiguration *config, toBeRemoved) { m_selectedTests.removeOne(config); delete config; @@ -243,10 +254,6 @@ void TestRunner::runTests() TestResultsPane::instance(), &TestResultsPane::addTestResult, Qt::QueuedConnection); - const QSharedPointer settings = AutotestPlugin::instance()->settings(); - const int timeout = settings->timeout; - const QString metricsOption = TestSettings::metricsTypeToOption(settings->metrics); - emit testRunStarted(); QFuture future = QtConcurrent::run(&performTestRun, m_selectedTests, timeout, metricsOption, this); diff --git a/plugins/autotest/testsettings.cpp b/plugins/autotest/testsettings.cpp index 17a9f7c7aa5..ce4c00d08d2 100644 --- a/plugins/autotest/testsettings.cpp +++ b/plugins/autotest/testsettings.cpp @@ -27,10 +27,11 @@ static const char group[] = "Autotest"; static const char timeoutKey[] = "Timeout"; static const char metricsKey[] = "Metrics"; static const char omitInternalKey[] = "OmitInternal"; +static const char omitRunConfigWarnKey[] = "OmitRCWarnings"; static const int defaultTimeout = 60000; TestSettings::TestSettings() - : timeout(defaultTimeout), metrics(Walltime), omitInternalMssg(true) + : timeout(defaultTimeout), metrics(Walltime), omitInternalMssg(true), omitRunConfigWarn(false) { } @@ -40,6 +41,7 @@ void TestSettings::toSettings(QSettings *s) const s->setValue(QLatin1String(timeoutKey), timeout); s->setValue(QLatin1String(metricsKey), metrics); s->setValue(QLatin1String(omitInternalKey), omitInternalMssg); + s->setValue(QLatin1String(omitRunConfigWarnKey), omitRunConfigWarn); s->endGroup(); } @@ -67,12 +69,14 @@ void TestSettings::fromSettings(const QSettings *s) timeout = s->value(root + QLatin1String(timeoutKey), defaultTimeout).toInt(); metrics = intToMetrics(s->value(root + QLatin1String(metricsKey), Walltime).toInt()); omitInternalMssg = s->value(root + QLatin1String(omitInternalKey), true).toBool(); + omitRunConfigWarn = s->value(root + QLatin1String(omitRunConfigWarnKey), false).toBool(); } bool TestSettings::equals(const TestSettings &rhs) const { return timeout == rhs.timeout && metrics == rhs.metrics - && omitInternalMssg == rhs.omitInternalMssg; + && omitInternalMssg == rhs.omitInternalMssg + && omitRunConfigWarn == rhs.omitRunConfigWarn; } QString TestSettings::metricsTypeToOption(const MetricsType type) diff --git a/plugins/autotest/testsettings.h b/plugins/autotest/testsettings.h index dc82647d105..44ab410093f 100644 --- a/plugins/autotest/testsettings.h +++ b/plugins/autotest/testsettings.h @@ -47,6 +47,7 @@ struct TestSettings int timeout; MetricsType metrics; bool omitInternalMssg; + bool omitRunConfigWarn; }; inline bool operator==(const TestSettings &s1, const TestSettings &s2) { return s1.equals(s2); } diff --git a/plugins/autotest/testsettingspage.cpp b/plugins/autotest/testsettingspage.cpp index 64be40bb9be..a41c287823e 100644 --- a/plugins/autotest/testsettingspage.cpp +++ b/plugins/autotest/testsettingspage.cpp @@ -39,6 +39,7 @@ void TestSettingsWidget::setSettings(const TestSettings &settings) { m_ui.timeoutSpin->setValue(settings.timeout / 1000); // we store milliseconds m_ui.omitInternalMsgCB->setChecked(settings.omitInternalMssg); + m_ui.omitRunConfigWarnCB->setChecked(settings.omitRunConfigWarn); switch (settings.metrics) { case MetricsType::Walltime: @@ -66,6 +67,7 @@ TestSettings TestSettingsWidget::settings() const TestSettings result; result.timeout = m_ui.timeoutSpin->value() * 1000; // we display seconds result.omitInternalMssg = m_ui.omitInternalMsgCB->isChecked(); + result.omitRunConfigWarn = m_ui.omitRunConfigWarnCB->isChecked(); if (m_ui.walltimeRB->isChecked()) result.metrics = MetricsType::Walltime; diff --git a/plugins/autotest/testsettingspage.ui b/plugins/autotest/testsettingspage.ui index 1a68db4b21b..164f9f7f5c1 100644 --- a/plugins/autotest/testsettingspage.ui +++ b/plugins/autotest/testsettingspage.ui @@ -6,252 +6,276 @@ 0 0 - 462 - 292 + 463 + 338 Form - - - - - - - - - - - Timeout used when executing test cases. This will apply for each test case on its own, not the whole project. - - - Timeout: - - - - - - - Timeout used when executing test cases. This will apply for each test case on its own, not the whole project. - - - s - - - 5 - - - 36000 - - - 60 - - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 40 - 20 - - - - - - - - If checked Internal Messages won't be shown by default. (You can still enable them on the test results filter) - - - Omit Internal Messages - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - - - - 0 - 0 - - - - Benchmark Metrics - - + + + + 9 + 10 + 435 + 307 + + + + + + + - + - - - - 0 - 0 - - + - Use Walltime metrics for executing benchmarks. (default) + Timeout used when executing test cases. This will apply for each test case on its own, not the whole project. - Walltime - - - true + Timeout: - - - - 0 - 0 - - + - Use tick counter for executing benchmarks. + Timeout used when executing test cases. This will apply for each test case on its own, not the whole project. - - Tickcounter + + s - - - - - - - 0 - 0 - + + 5 - - Use event counter when executing benchmarks. + + 36000 - - Eventcounter - - - - - - - false - - - - 0 - 0 - - - - Use callgrind when executing benchmark. (valgrind must be installed) - - - Callgrind - - - - - - - false - - - - 0 - 0 - - - - Use perf when executing benchmarks. (perf must be installed) - - - Perf + + 60 - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 40 + 20 + + + + + + + + + + If checked Internal Messages won't be shown by default. (You can still enable them on the test results filter) + + + Omit Internal Messages + + + true + + + + + + + If checked Warnings regarding a guessed Run Configuration won't be shown. + + + Omit Run Configuration Warnings + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + + + 0 + 0 + + + + Benchmark Metrics + + + + + + + + + 0 + 0 + + + + Use Walltime metrics for executing benchmarks. (default) + + + Walltime + + + true + + + + + + + + 0 + 0 + + + + Use tick counter for executing benchmarks. + + + Tickcounter + + + + + + + + 0 + 0 + + + + Use event counter when executing benchmarks. + + + Eventcounter + + + + + + + false + + + + 0 + 0 + + + + Use callgrind when executing benchmark. (valgrind must be installed) + + + Callgrind + + + + + + + false + + + + 0 + 0 + + + + Use perf when executing benchmarks. (perf must be installed) + + + Perf + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 66abadd96a0..ea2832451d6 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -385,8 +386,10 @@ static void addProjectInformation(TestConfiguration *config, const QString &file QString workDir; QString proFile; QString displayName; + ProjectExplorer::Project *targetProject = 0; Utils::Environment env; bool hasDesktopTarget = false; + bool guessedRunConfiguration = false; CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); QList projParts = cppMM->projectInfo(project).projectParts(); @@ -396,6 +399,7 @@ static void addProjectInformation(TestConfiguration *config, const QString &file if (currentFile.path == filePath) { proFile = part->projectFile; displayName = part->displayName; + targetProject = part->project; break; } } @@ -429,6 +433,34 @@ static void addProjectInformation(TestConfiguration *config, const QString &file break; } } + + // if we could not figure out the run configuration + // try to use the run configuration of the parent project + if (!hasDesktopTarget && targetProject && !targetFile.isEmpty()) { + QList rcs = target->runConfigurations(); + foreach (ProjectExplorer::RunConfiguration *rc, rcs) { + ProjectExplorer::LocalApplicationRunConfiguration *localRunConfiguration + = qobject_cast(rc); + if (localRunConfiguration) { + if (ProjectExplorer::ProjectNode *localRootProjectNode = targetProject->rootProjectNode()) { + QList localFileNodes = localRootProjectNode->fileNodes(); + if (localFileNodes.size()) { + if (localFileNodes.at(0)->path() + == targetProject->projectFilePath()) { + hasDesktopTarget = true; + workDir = Utils::FileUtils::normalizePathName( + localRunConfiguration->workingDirectory()); + ProjectExplorer::EnvironmentAspect *environmentAspect + = localRunConfiguration->extraAspect(); + env = environmentAspect->environment(); + guessedRunConfiguration = true; + break; + } + } + } + } + } + } } } @@ -440,6 +472,7 @@ static void addProjectInformation(TestConfiguration *config, const QString &file config->setEnvironment(env); config->setProject(project); config->setDisplayName(displayName); + config->setGuessedConfiguration(guessedRunConfiguration); } else { config->setProFile(proFile); config->setDisplayName(displayName); From 0a7b2b76cbf0ff666c3bb69f1e96041b94e6b312 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 17 Feb 2015 14:45:26 +0100 Subject: [PATCH 067/200] Display progress indicator on navigation view... ...if parsing takes longer. Change-Id: Ib311c031ae0af72b2f923d93578099687d9af91a Reviewed-by: Eike Ziller --- plugins/autotest/testcodeparser.cpp | 2 ++ plugins/autotest/testcodeparser.h | 1 + plugins/autotest/testnavigationwidget.cpp | 28 +++++++++++++++++++++++ plugins/autotest/testnavigationwidget.h | 10 +++++++- 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 09c0db02921..d0c209224c0 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -620,6 +620,8 @@ void TestCodeParser::scanForTests(const QStringList &fileList) Autotest::Constants::TASK_PARSE); connect(progress, &Core::FutureProgress::finished, this, &TestCodeParser::onFinished); + + emit parsingStarted(); } void TestCodeParser::clearCache() diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index f2bb6de13ef..88c2b223caf 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -70,6 +70,7 @@ signals: void unnamedQuickTestsUpdated(const QString &filePath, const QString &mainFile, const QMap &functions); void unnamedQuickTestsRemoved(const QString &filePath); + void parsingStarted(); void parsingFinished(); void partialParsingFinished(); diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index 83384556232..db7776fbd27 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -29,7 +29,9 @@ #include #include #include +#include +#include #include #include @@ -55,6 +57,21 @@ TestNavigationWidget::TestNavigationWidget(QWidget *parent) : setLayout(layout); connect(m_view, &TestTreeView::activated, this, &TestNavigationWidget::onItemActivated); + + m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicator::Medium, this); + m_progressIndicator->attachToWidget(m_view); + m_progressIndicator->hide(); + + m_progressTimer = new QTimer(this); + m_progressTimer->setSingleShot(true); + m_progressTimer->setInterval(100); // don't display indicator if progress takes less than 100ms + + connect(m_model->parser(), &TestCodeParser::parsingStarted, + this, &TestNavigationWidget::onParsingStarted); + connect(m_model->parser(), &TestCodeParser::parsingFinished, + this, &TestNavigationWidget::onParsingFinished); + connect(m_progressTimer, &QTimer::timeout, + m_progressIndicator, &Utils::ProgresssIndicator::show); } TestNavigationWidget::~TestNavigationWidget() @@ -178,6 +195,17 @@ void TestNavigationWidget::onFilterMenuTriggered(QAction *action) TestTreeSortFilterModel::toFilterMode(action->data().value())); } +void TestNavigationWidget::onParsingStarted() +{ + m_progressTimer->start(); +} + +void TestNavigationWidget::onParsingFinished() +{ + m_progressTimer->stop(); + m_progressIndicator->hide(); +} + void TestNavigationWidget::initializeFilterMenu() { QAction *action = new QAction(m_filterMenu); diff --git a/plugins/autotest/testnavigationwidget.h b/plugins/autotest/testnavigationwidget.h index 50d6ae8970a..3ea77536638 100644 --- a/plugins/autotest/testnavigationwidget.h +++ b/plugins/autotest/testnavigationwidget.h @@ -26,6 +26,7 @@ QT_BEGIN_NAMESPACE class QAction; class QMenu; +class QTimer; class QToolButton; QT_END_NAMESPACE @@ -33,6 +34,10 @@ namespace Core { class IContext; } +namespace Utils { +class ProgressIndicator; +} + namespace Autotest { namespace Internal { @@ -60,6 +65,8 @@ private slots: void onRunSelectedTriggered(); void onSortClicked(); void onFilterMenuTriggered(QAction *action); + void onParsingStarted(); + void onParsingFinished(); private: void initializeFilterMenu(); @@ -71,7 +78,8 @@ private: QToolButton *m_filterButton; QMenu *m_filterMenu; bool m_sortAlphabetically; - + Utils::ProgressIndicator *m_progressIndicator; + QTimer *m_progressTimer; }; class TestNavigationWidgetFactory : public Core::INavigationWidgetFactory From e3f4ca4185d4681ae04fc6f9b6c146a131b09090 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 18 Feb 2015 08:31:18 +0100 Subject: [PATCH 068/200] Fix compile Change-Id: I98c609dde6a48628561beca969ccd108361758dc Reviewed-by: Christian Stenger --- plugins/autotest/testnavigationwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index db7776fbd27..2a5bf152e33 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -71,7 +71,7 @@ TestNavigationWidget::TestNavigationWidget(QWidget *parent) : connect(m_model->parser(), &TestCodeParser::parsingFinished, this, &TestNavigationWidget::onParsingFinished); connect(m_progressTimer, &QTimer::timeout, - m_progressIndicator, &Utils::ProgresssIndicator::show); + m_progressIndicator, &Utils::ProgressIndicator::show); } TestNavigationWidget::~TestNavigationWidget() From f6c973249d5ee08a750df7bcb4ebe8e1a5d9b88e Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 18 Feb 2015 15:40:32 +0100 Subject: [PATCH 069/200] Fix include type. Change-Id: Ibf9e205c3b2faf46216043c9061209cb29c13b04 Reviewed-by: Christian Stenger --- plugins/autotest/testxmloutputreader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/autotest/testxmloutputreader.h b/plugins/autotest/testxmloutputreader.h index 6d15a2b885c..436dd5fc682 100644 --- a/plugins/autotest/testxmloutputreader.h +++ b/plugins/autotest/testxmloutputreader.h @@ -19,7 +19,7 @@ #ifndef TESTXMLOUTPUTREADER_H #define TESTXMLOUTPUTREADER_H -#include +#include "testresult.h" #include #include From 2bd868b685a2b0cff5399b0340745097d1a79c0c Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 18 Feb 2015 15:41:47 +0100 Subject: [PATCH 070/200] Add qbs project file. Change-Id: I36368fa8c5478bc688819ea23152f8272ff5cfa9 Reviewed-by: Christian Stenger --- plugins/autotest/autotest.qbs | 80 +++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 plugins/autotest/autotest.qbs diff --git a/plugins/autotest/autotest.qbs b/plugins/autotest/autotest.qbs new file mode 100644 index 00000000000..8b522b6eb62 --- /dev/null +++ b/plugins/autotest/autotest.qbs @@ -0,0 +1,80 @@ +import qbs + +QtcPlugin { + name: "AutoTest" + + Depends { name: "Core" } + Depends { name: "CppTools" } + Depends { name: "CPlusPlus" } + Depends { name: "LicenseChecker" } + Depends { name: "ProjectExplorer" } + Depends { name: "QmakeProjectManager" } + Depends { name: "QmlJS" } + Depends { name: "QmlJSTools" } + Depends { name: "Utils" } + + Depends { + name: "QtSupport" + condition: project.testsEnabled + } + + Depends { + name: "Qt.test" + condition: project.testsEnabled + } + + Depends { name: "Qt.widgets" } + + files: [ + "autotest.qrc", + "autotest_global.h", + "autotestconstants.h", + "autotestplugin.cpp", + "autotestplugin.h", + "testcodeparser.cpp", + "testcodeparser.h", + "testconfiguration.cpp", + "testconfiguration.h", + "testinfo.cpp", + "testinfo.h", + "testnavigationwidget.cpp", + "testnavigationwidget.h", + "testresult.cpp", + "testresult.h", + "testresultdelegate.cpp", + "testresultdelegate.h", + "testresultmodel.cpp", + "testresultmodel.h", + "testresultspane.cpp", + "testresultspane.h", + "testrunner.cpp", + "testrunner.h", + "testsettings.cpp", + "testsettings.h", + "testsettingspage.cpp", + "testsettingspage.h", + "testsettingspage.ui", + "testtreeitem.cpp", + "testtreeitem.h", + "testtreeitemdelegate.cpp", + "testtreeitemdelegate.h", + "testtreemodel.cpp", + "testtreemodel.h", + "testtreeview.cpp", + "testtreeview.h", + "testvisitor.cpp", + "testvisitor.h", + "testxmloutputreader.cpp", + "testxmloutputreader.h", + ] + + Group { + name: "Test sources" + condition: project.testsEnabled + files: [ + "autotestunittests.cpp", + "autotestunittests.h", + "autotestunittests.qrc", + ] + } +} From 7f5db665969865cd6a72841887dddb87a06fd5b9 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 19 Feb 2015 08:09:02 +0100 Subject: [PATCH 071/200] Fix copyright headers Change-Id: If02fedb7c191492ddfaf2eb34e74fcdb7a007c94 Reviewed-by: Christian Stenger --- plugins/autotest/AutoTest.json.in | 8 ++++---- plugins/autotest/autotest_global.h | 9 +++++---- plugins/autotest/autotestconstants.h | 9 +++++---- plugins/autotest/autotestplugin.cpp | 9 +++++---- plugins/autotest/autotestplugin.h | 9 +++++---- plugins/autotest/autotestunittests.cpp | 9 +++++---- plugins/autotest/autotestunittests.h | 9 +++++---- plugins/autotest/testcodeparser.cpp | 9 +++++---- plugins/autotest/testcodeparser.h | 9 +++++---- plugins/autotest/testconfiguration.cpp | 9 +++++---- plugins/autotest/testconfiguration.h | 9 +++++---- plugins/autotest/testinfo.cpp | 9 +++++---- plugins/autotest/testinfo.h | 9 +++++---- plugins/autotest/testnavigationwidget.cpp | 9 +++++---- plugins/autotest/testnavigationwidget.h | 9 +++++---- plugins/autotest/testresult.cpp | 9 +++++---- plugins/autotest/testresult.h | 9 +++++---- plugins/autotest/testresultdelegate.cpp | 9 +++++---- plugins/autotest/testresultdelegate.h | 9 +++++---- plugins/autotest/testresultmodel.cpp | 9 +++++---- plugins/autotest/testresultmodel.h | 9 +++++---- plugins/autotest/testresultspane.cpp | 9 +++++---- plugins/autotest/testresultspane.h | 9 +++++---- plugins/autotest/testrunner.cpp | 9 +++++---- plugins/autotest/testrunner.h | 9 +++++---- plugins/autotest/testsettings.cpp | 9 +++++---- plugins/autotest/testsettings.h | 9 +++++---- plugins/autotest/testsettingspage.cpp | 9 +++++---- plugins/autotest/testsettingspage.h | 9 +++++---- plugins/autotest/testtreeitem.cpp | 9 +++++---- plugins/autotest/testtreeitem.h | 9 +++++---- plugins/autotest/testtreeitemdelegate.cpp | 9 +++++---- plugins/autotest/testtreeitemdelegate.h | 9 +++++---- plugins/autotest/testtreemodel.cpp | 9 +++++---- plugins/autotest/testtreemodel.h | 9 +++++---- plugins/autotest/testtreeview.cpp | 9 +++++---- plugins/autotest/testtreeview.h | 9 +++++---- plugins/autotest/testvisitor.cpp | 9 +++++---- plugins/autotest/testvisitor.h | 9 +++++---- plugins/autotest/testxmloutputreader.cpp | 9 +++++---- plugins/autotest/testxmloutputreader.h | 9 +++++---- .../mixed_atp/tests/auto/bench/tst_benchtest.cpp | 9 +++++---- .../unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp | 9 +++++---- .../unit_test/mixed_atp/tests/auto/dummy/tst_foo.h | 9 +++++---- .../unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp | 9 +++++---- .../mixed_atp/tests/auto/quickauto/bar/tst_foo.qml | 9 +++++---- .../mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml | 9 +++++---- .../mixed_atp/tests/auto/quickauto/tst_test1.qml | 9 +++++---- .../mixed_atp/tests/auto/quickauto/tst_test2.qml | 9 +++++---- .../mixed_atp/tests/auto/quickauto/tst_test3.qml | 9 +++++---- .../mixed_atp/tests/auto/quickauto2/tst_test1.qml | 9 +++++---- .../mixed_atp/tests/auto/quickauto2/tst_test2.qml | 9 +++++---- .../autotest/unit_test/plain/test_plain/tst_simple.cpp | 9 +++++---- 53 files changed, 264 insertions(+), 212 deletions(-) diff --git a/plugins/autotest/AutoTest.json.in b/plugins/autotest/AutoTest.json.in index dd25f250d26..415347eec15 100644 --- a/plugins/autotest/AutoTest.json.in +++ b/plugins/autotest/AutoTest.json.in @@ -3,13 +3,13 @@ \"Version\" : \"$$QTCREATOR_VERSION\", \"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\", \"Experimental\" : true, -\"Vendor\" : \"Digia Plc\", -\"Copyright\" : \"(C) 2014 Digia Plc\", +\"Vendor\" : \"The Qt Company Ltd\", +\"Copyright\" : \"(C) 2015 The Qt Company Ltd\", \"License\" : [ \"Commercial Usage\", \"\", -\"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Digia.\" +\"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and The Qt Company.\" ], \"Description\" : \"Auto Test plugin.\", -\"Url\" : \"http://qt.digia.com\", +\"Url\" : \"http://www.qt.io\", $$dependencyList } diff --git a/plugins/autotest/autotest_global.h b/plugins/autotest/autotest_global.h index 3f3c6ae192a..1d945af7657 100644 --- a/plugins/autotest/autotest_global.h +++ b/plugins/autotest/autotest_global.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/autotestconstants.h b/plugins/autotest/autotestconstants.h index c82c5efbca2..d1ed6590791 100644 --- a/plugins/autotest/autotestconstants.h +++ b/plugins/autotest/autotestconstants.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index 82e20e82c33..581ed8a195e 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/autotestplugin.h b/plugins/autotest/autotestplugin.h index aab664bc2d4..8bf2664b40b 100644 --- a/plugins/autotest/autotestplugin.h +++ b/plugins/autotest/autotestplugin.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/autotestunittests.cpp b/plugins/autotest/autotestunittests.cpp index 1010bbc1918..15f32db669c 100644 --- a/plugins/autotest/autotestunittests.cpp +++ b/plugins/autotest/autotestunittests.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/autotestunittests.h b/plugins/autotest/autotestunittests.h index 16c6042b5dc..ab2b7c1b9b4 100644 --- a/plugins/autotest/autotestunittests.h +++ b/plugins/autotest/autotestunittests.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index d0c209224c0..6577b5197f1 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 88c2b223caf..c4ca773f388 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testconfiguration.cpp b/plugins/autotest/testconfiguration.cpp index a8ca3743349..7c161289ef4 100644 --- a/plugins/autotest/testconfiguration.cpp +++ b/plugins/autotest/testconfiguration.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testconfiguration.h b/plugins/autotest/testconfiguration.h index 82fb874ca48..aff75d64058 100644 --- a/plugins/autotest/testconfiguration.h +++ b/plugins/autotest/testconfiguration.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testinfo.cpp b/plugins/autotest/testinfo.cpp index e3e13274f7c..b83c8b61d13 100644 --- a/plugins/autotest/testinfo.cpp +++ b/plugins/autotest/testinfo.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testinfo.h b/plugins/autotest/testinfo.h index cadd57212f9..21fc1200838 100644 --- a/plugins/autotest/testinfo.h +++ b/plugins/autotest/testinfo.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index 2a5bf152e33..b58e8a6b528 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testnavigationwidget.h b/plugins/autotest/testnavigationwidget.h index 3ea77536638..5e0ec2197ef 100644 --- a/plugins/autotest/testnavigationwidget.h +++ b/plugins/autotest/testnavigationwidget.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp index 5e878955603..6a054a4c7d4 100644 --- a/plugins/autotest/testresult.cpp +++ b/plugins/autotest/testresult.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index 086b0fd21dc..c1d6d5eac42 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp index e6df02dc9fb..32aa33df5e3 100644 --- a/plugins/autotest/testresultdelegate.cpp +++ b/plugins/autotest/testresultdelegate.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testresultdelegate.h b/plugins/autotest/testresultdelegate.h index 2b85ae1076d..0627ed5ee59 100644 --- a/plugins/autotest/testresultdelegate.h +++ b/plugins/autotest/testresultdelegate.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index f0324458c38..07040014885 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testresultmodel.h b/plugins/autotest/testresultmodel.h index 5747194a88b..c10bc44013d 100644 --- a/plugins/autotest/testresultmodel.h +++ b/plugins/autotest/testresultmodel.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index cb93d156faa..6985a7d86f0 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h index 3567bd292ec..e2d7c6746fa 100644 --- a/plugins/autotest/testresultspane.h +++ b/plugins/autotest/testresultspane.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 150e72750d4..6b1c68a9d4e 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ #include "testrunner.h" diff --git a/plugins/autotest/testrunner.h b/plugins/autotest/testrunner.h index a5e472d2237..ddbac5e92f7 100644 --- a/plugins/autotest/testrunner.h +++ b/plugins/autotest/testrunner.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testsettings.cpp b/plugins/autotest/testsettings.cpp index ce4c00d08d2..06567842157 100644 --- a/plugins/autotest/testsettings.cpp +++ b/plugins/autotest/testsettings.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testsettings.h b/plugins/autotest/testsettings.h index 44ab410093f..c7ff22c3ff2 100644 --- a/plugins/autotest/testsettings.h +++ b/plugins/autotest/testsettings.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testsettingspage.cpp b/plugins/autotest/testsettingspage.cpp index a41c287823e..53ab2c71a10 100644 --- a/plugins/autotest/testsettingspage.cpp +++ b/plugins/autotest/testsettingspage.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testsettingspage.h b/plugins/autotest/testsettingspage.h index cc30026fe27..3e98c8413de 100644 --- a/plugins/autotest/testsettingspage.h +++ b/plugins/autotest/testsettingspage.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index f3771183134..721c605473e 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index e1814db356f..0cfa1aead11 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testtreeitemdelegate.cpp b/plugins/autotest/testtreeitemdelegate.cpp index 71ccef57560..1e5952c7a02 100644 --- a/plugins/autotest/testtreeitemdelegate.cpp +++ b/plugins/autotest/testtreeitemdelegate.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testtreeitemdelegate.h b/plugins/autotest/testtreeitemdelegate.h index af31022b0bc..d4777f438cb 100644 --- a/plugins/autotest/testtreeitemdelegate.h +++ b/plugins/autotest/testtreeitemdelegate.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index ea2832451d6..0b21ec3cea9 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 44186285a9f..f1229cedf52 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testtreeview.cpp b/plugins/autotest/testtreeview.cpp index 704067a6371..5675e9266f8 100644 --- a/plugins/autotest/testtreeview.cpp +++ b/plugins/autotest/testtreeview.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testtreeview.h b/plugins/autotest/testtreeview.h index 9865e69df27..c9a4d9f9ff1 100644 --- a/plugins/autotest/testtreeview.h +++ b/plugins/autotest/testtreeview.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testvisitor.cpp b/plugins/autotest/testvisitor.cpp index b6706b5bf4c..b43a0c02712 100644 --- a/plugins/autotest/testvisitor.cpp +++ b/plugins/autotest/testvisitor.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testvisitor.h b/plugins/autotest/testvisitor.h index ae6b844ca2b..279aca6cbe5 100644 --- a/plugins/autotest/testvisitor.h +++ b/plugins/autotest/testvisitor.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testxmloutputreader.cpp b/plugins/autotest/testxmloutputreader.cpp index 193b716a267..31d21b959ad 100644 --- a/plugins/autotest/testxmloutputreader.cpp +++ b/plugins/autotest/testxmloutputreader.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/testxmloutputreader.h b/plugins/autotest/testxmloutputreader.h index 436dd5fc682..1ca22b96989 100644 --- a/plugins/autotest/testxmloutputreader.h +++ b/plugins/autotest/testxmloutputreader.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp b/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp index 1d968a01470..bd00dda5637 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ #include diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp index 9dc2c9ec3a4..caac56ff037 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ #include "tst_foo.h" diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h index 29bb8f5f6e4..f9b95a2bd7b 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ #ifndef FOO_H_INCLUDED diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp b/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp index 13d61ba1519..5681ce1fd37 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ #include diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml index ff825cd9896..da2196e79d7 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ import QtQuick 2.0 diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml index 325b7c49276..b6f04f5389d 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ import QtQuick 2.0 diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml index 8bf1379dc9c..67d2965452e 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ import QtQuick 2.0 diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml index c9a7f5286b7..02331ec9a0a 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ import QtQuick 2.0 diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml index 3575c6b3132..8d362d1dd95 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ import QtQuick 2.0 diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml index 8bf1379dc9c..67d2965452e 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ import QtQuick 2.0 diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml index a72913a84ed..1c3465b1c32 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ import QtQuick 2.0 diff --git a/plugins/autotest/unit_test/plain/test_plain/tst_simple.cpp b/plugins/autotest/unit_test/plain/test_plain/tst_simple.cpp index 785aa6a1c8a..864883f75ba 100644 --- a/plugins/autotest/unit_test/plain/test_plain/tst_simple.cpp +++ b/plugins/autotest/unit_test/plain/test_plain/tst_simple.cpp @@ -1,18 +1,19 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us ** ** This file is part of the Qt Creator Enterprise Auto Test Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ #include "tst_simple.h" From 01eb2ad24fc90ba5cf21e703d7bebe7538bd14ba Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Thu, 26 Feb 2015 16:50:39 +0100 Subject: [PATCH 072/200] Compile fix: Add missing includes Change-Id: Ie93829eb73888646fcfd76746cd74bd7c1b09924 Reviewed-by: Tobias Hunger --- plugins/autotest/testcodeparser.cpp | 1 + plugins/autotest/testnavigationwidget.cpp | 3 +++ plugins/autotest/testresultspane.cpp | 2 ++ 3 files changed, 6 insertions(+) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 6577b5197f1..ed8e1facf4f 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -22,6 +22,7 @@ #include "testinfo.h" #include "testvisitor.h" +#include #include #include diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index b58e8a6b528..e23ebb5c885 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -26,12 +26,15 @@ #include "autotestconstants.h" #include "testtreeitem.h" +#include #include #include #include #include #include +#include +#include #include #include #include diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 6985a7d86f0..6b50fd5fd63 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -26,6 +26,7 @@ #include "testtreemodel.h" #include +#include #include #include @@ -35,6 +36,7 @@ #include #include +#include #include #include From 9eb616718903e9f3b64f96d3fe72b3ec5d525263 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 19 Feb 2015 11:19:59 +0100 Subject: [PATCH 073/200] Improve handling of disabled parser and re-enabling parser Instead of always parsing again when re-enabling parser do it only if there are changes of the current project. If the current project has not changed since last parsing just rely on the cached information. Change-Id: I7681318132f37172730648604ddbecf1cd37d177 Reviewed-by: Oliver Wolff Reviewed-by: Christian Stenger --- plugins/autotest/testcodeparser.cpp | 56 ++++++++++++++++++++--------- plugins/autotest/testcodeparser.h | 1 + plugins/autotest/testtreemodel.cpp | 32 ++--------------- plugins/autotest/testtreemodel.h | 2 -- 4 files changed, 42 insertions(+), 49 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index ed8e1facf4f..004168ab6aa 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -59,7 +59,8 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent) m_pendingUpdate(false), m_fullUpdatePostPoned(false), m_partialUpdatePostPoned(false), - m_parserState(Idle) + m_dirty(true), + m_parserState(Disabled) { // connect to ProgressManager to post-pone test parsing when CppModelManager is parsing auto progressManager = qobject_cast(Core::ProgressManager::instance()); @@ -76,20 +77,6 @@ TestCodeParser::~TestCodeParser() clearCache(); } -void TestCodeParser::setState(State state) -{ - m_parserState = state; - if (m_parserState == Disabled) { - m_pendingUpdate = m_fullUpdatePostPoned = m_partialUpdatePostPoned = false; - m_postPonedFiles.clear(); - } -} - -void TestCodeParser::emitUpdateTestTree() -{ - QTimer::singleShot(1000, this, SLOT(updateTestTree())); -} - ProjectExplorer::Project *currentProject() { const ProjectExplorer::SessionManager *session = ProjectExplorer::SessionManager::instance(); @@ -98,6 +85,22 @@ ProjectExplorer::Project *currentProject() return session->startupProject(); } +void TestCodeParser::setState(State state) +{ + m_parserState = state; + if (m_parserState == Disabled) { + m_pendingUpdate = m_fullUpdatePostPoned = m_partialUpdatePostPoned = false; + m_postPonedFiles.clear(); + } else if (m_parserState == Idle && m_dirty && currentProject()) { + scanForTests(m_postPonedFiles.toList()); + } +} + +void TestCodeParser::emitUpdateTestTree() +{ + QTimer::singleShot(1000, this, SLOT(updateTestTree())); +} + void TestCodeParser::updateTestTree() { if (!m_parserEnabled) { @@ -578,14 +581,29 @@ bool TestCodeParser::postponed(const QStringList &fileList) } return true; case Disabled: - qWarning("Checking for postponing but being disabled..."); - return false; + break; } QTC_ASSERT(false, return false); // should not happen at all } void TestCodeParser::scanForTests(const QStringList &fileList) { + if (m_parserState == Disabled) { + m_dirty = true; + if (fileList.isEmpty()) { + m_fullUpdatePostPoned = true; + m_partialUpdatePostPoned = false; + m_postPonedFiles.clear(); + } else { + if (!m_fullUpdatePostPoned) { + m_partialUpdatePostPoned = true; + foreach (const QString &file, fileList) + m_postPonedFiles.insert(file); + } + } + return; + } + if (postponed(fileList)) return; @@ -730,6 +748,7 @@ void TestCodeParser::onFinished() case FullParse: m_parserState = Idle; emit parsingFinished(); + m_dirty = false; break; default: qWarning("I should not be here..."); @@ -752,6 +771,9 @@ void TestCodeParser::onPartialParsingFinished() tmp << file; m_postPonedFiles.clear(); scanForTests(tmp); + } else { + m_dirty = false; + emit parsingFinished(); } } diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index c4ca773f388..85582d1d5d6 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -113,6 +113,7 @@ private: bool m_pendingUpdate; bool m_fullUpdatePostPoned; bool m_partialUpdatePostPoned; + bool m_dirty; QSet m_postPonedFiles; State m_parserState; }; diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 0b21ec3cea9..e707aaa052e 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -51,8 +51,7 @@ TestTreeModel::TestTreeModel(QObject *parent) : m_autoTestRootItem(new TestTreeItem(tr("Auto Tests"), QString(), TestTreeItem::ROOT, m_rootItem)), m_quickTestRootItem(new TestTreeItem(tr("Qt Quick Tests"), QString(), TestTreeItem::ROOT, m_rootItem)), m_parser(new TestCodeParser(this)), - m_connectionsInitialized(false), - m_initializationCounter(0) + m_connectionsInitialized(false) { m_rootItem->appendChild(m_autoTestRootItem); m_rootItem->appendChild(m_quickTestRootItem); @@ -103,13 +102,10 @@ TestTreeModel::~TestTreeModel() void TestTreeModel::enableParsing() { - ++m_initializationCounter; - + m_parser->setState(TestCodeParser::Idle); if (m_connectionsInitialized) return; - m_parser->setState(TestCodeParser::Idle); - ProjectExplorer::SessionManager *sm = ProjectExplorer::SessionManager::instance(); connect(sm, &ProjectExplorer::SessionManager::startupProjectChanged, m_parser, &TestCodeParser::emitUpdateTestTree); @@ -126,35 +122,11 @@ void TestTreeModel::enableParsing() connect(qmlJsMM, &QmlJS::ModelManagerInterface::aboutToRemoveFiles, m_parser, &TestCodeParser::removeFiles, Qt::QueuedConnection); m_connectionsInitialized = true; - m_parser->updateTestTree(); } void TestTreeModel::disableParsing() { - if (!m_connectionsInitialized) - return; - if (--m_initializationCounter != 0) - return; - - ProjectExplorer::SessionManager *sm = ProjectExplorer::SessionManager::instance(); - disconnect(sm, &ProjectExplorer::SessionManager::startupProjectChanged, - m_parser, &TestCodeParser::emitUpdateTestTree); - - CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); - disconnect(cppMM, &CppTools::CppModelManager::documentUpdated, - m_parser, &TestCodeParser::onCppDocumentUpdated); - disconnect(cppMM, &CppTools::CppModelManager::aboutToRemoveFiles, - m_parser, &TestCodeParser::removeFiles); - - QmlJS::ModelManagerInterface *qmlJsMM = QmlJS::ModelManagerInterface::instance(); - disconnect(qmlJsMM, &QmlJS::ModelManagerInterface::documentUpdated, - m_parser, &TestCodeParser::onQmlDocumentUpdated); - disconnect(qmlJsMM, &QmlJS::ModelManagerInterface::aboutToRemoveFiles, - m_parser, &TestCodeParser::removeFiles); - m_parser->setState(TestCodeParser::Disabled); - - m_connectionsInitialized = false; } QModelIndex TestTreeModel::index(int row, int column, const QModelIndex &parent) const diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index f1229cedf52..437aa787bec 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -113,8 +113,6 @@ private: TestTreeItem *m_quickTestRootItem; TestCodeParser *m_parser; bool m_connectionsInitialized; - int m_initializationCounter; - }; class TestTreeSortFilterModel : public QSortFilterProxyModel From 2b8d6c5fc4af14c5e2377d36b01f61d485c700d7 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 20 Feb 2015 09:11:33 +0100 Subject: [PATCH 074/200] Remove useless member No need to have another member variable for almost the same functionality. Consolidated where necessary. Change-Id: Iefaa410fea527f88b18b406199a449fc9e4d0533 Reviewed-by: Oliver Wolff Reviewed-by: Christian Stenger --- plugins/autotest/testcodeparser.cpp | 15 +++++++-------- plugins/autotest/testcodeparser.h | 1 - 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 004168ab6aa..8c719361fac 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -56,7 +56,6 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent) : QObject(parent), m_model(parent), m_parserEnabled(true), - m_pendingUpdate(false), m_fullUpdatePostPoned(false), m_partialUpdatePostPoned(false), m_dirty(true), @@ -89,7 +88,7 @@ void TestCodeParser::setState(State state) { m_parserState = state; if (m_parserState == Disabled) { - m_pendingUpdate = m_fullUpdatePostPoned = m_partialUpdatePostPoned = false; + m_fullUpdatePostPoned = m_partialUpdatePostPoned = false; m_postPonedFiles.clear(); } else if (m_parserState == Idle && m_dirty && currentProject()) { scanForTests(m_postPonedFiles.toList()); @@ -104,14 +103,14 @@ void TestCodeParser::emitUpdateTestTree() void TestCodeParser::updateTestTree() { if (!m_parserEnabled) { - m_pendingUpdate = true; + m_fullUpdatePostPoned = true; return; } if (ProjectExplorer::Project *project = currentProject()) { if (auto qmakeProject = qobject_cast(project)) { if (qmakeProject->asyncUpdateState() != QmakeProjectManager::QmakeProject::Base) { - m_pendingUpdate = true; + m_fullUpdatePostPoned = true; return; } connect(qmakeProject, &QmakeProjectManager::QmakeProject::proFilesEvaluated, @@ -120,7 +119,7 @@ void TestCodeParser::updateTestTree() } else return; - m_pendingUpdate = false; + m_fullUpdatePostPoned = false; clearCache(); emit cacheCleared(); @@ -476,7 +475,7 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr document) void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document) { if (!m_parserEnabled) { - if (!m_pendingUpdate) { + if (!m_fullUpdatePostPoned) { m_partialUpdatePostPoned = true; m_postPonedFiles.insert(document->fileName()); } @@ -501,7 +500,7 @@ void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &docume void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) { if (!m_parserEnabled) { - if (!m_pendingUpdate) { + if (!m_fullUpdatePostPoned) { m_partialUpdatePostPoned = true; m_postPonedFiles.insert(document->fileName()); } @@ -726,7 +725,7 @@ void TestCodeParser::onAllTasksFinished(Core::Id type) if (type != CppTools::Constants::TASK_INDEX) return; m_parserEnabled = true; - if (m_pendingUpdate) + if (m_fullUpdatePostPoned) updateTestTree(); else if (m_partialUpdatePostPoned) { m_partialUpdatePostPoned = false; diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 85582d1d5d6..d2785766ac8 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -110,7 +110,6 @@ private: QMap m_quickDocMap; QList m_unnamedQuickDocList; bool m_parserEnabled; - bool m_pendingUpdate; bool m_fullUpdatePostPoned; bool m_partialUpdatePostPoned; bool m_dirty; From 6a3b43fef023d318eef1706bf61bf9bcb0829e16 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 27 Feb 2015 14:16:07 +0100 Subject: [PATCH 075/200] Fix camel-case of *postponed* Change-Id: Ie00c35bceba3b772f68e2d9b665af8427a105433 Reviewed-by: Oliver Wolff --- plugins/autotest/testcodeparser.cpp | 94 ++++++++++++++--------------- plugins/autotest/testcodeparser.h | 6 +- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 8c719361fac..cd18623cad4 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -56,12 +56,12 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent) : QObject(parent), m_model(parent), m_parserEnabled(true), - m_fullUpdatePostPoned(false), - m_partialUpdatePostPoned(false), + m_fullUpdatePostponed(false), + m_partialUpdatePostponed(false), m_dirty(true), m_parserState(Disabled) { - // connect to ProgressManager to post-pone test parsing when CppModelManager is parsing + // connect to ProgressManager to postpone test parsing when CppModelManager is parsing auto progressManager = qobject_cast(Core::ProgressManager::instance()); connect(progressManager, &Core::ProgressManager::taskStarted, this, &TestCodeParser::onTaskStarted); @@ -88,10 +88,10 @@ void TestCodeParser::setState(State state) { m_parserState = state; if (m_parserState == Disabled) { - m_fullUpdatePostPoned = m_partialUpdatePostPoned = false; - m_postPonedFiles.clear(); + m_fullUpdatePostponed = m_partialUpdatePostponed = false; + m_postponedFiles.clear(); } else if (m_parserState == Idle && m_dirty && currentProject()) { - scanForTests(m_postPonedFiles.toList()); + scanForTests(m_postponedFiles.toList()); } } @@ -103,14 +103,14 @@ void TestCodeParser::emitUpdateTestTree() void TestCodeParser::updateTestTree() { if (!m_parserEnabled) { - m_fullUpdatePostPoned = true; + m_fullUpdatePostponed = true; return; } if (ProjectExplorer::Project *project = currentProject()) { if (auto qmakeProject = qobject_cast(project)) { if (qmakeProject->asyncUpdateState() != QmakeProjectManager::QmakeProject::Base) { - m_fullUpdatePostPoned = true; + m_fullUpdatePostponed = true; return; } connect(qmakeProject, &QmakeProjectManager::QmakeProject::proFilesEvaluated, @@ -119,7 +119,7 @@ void TestCodeParser::updateTestTree() } else return; - m_fullUpdatePostPoned = false; + m_fullUpdatePostponed = false; clearCache(); emit cacheCleared(); @@ -475,9 +475,9 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr document) void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document) { if (!m_parserEnabled) { - if (!m_fullUpdatePostPoned) { - m_partialUpdatePostPoned = true; - m_postPonedFiles.insert(document->fileName()); + if (!m_fullUpdatePostponed) { + m_partialUpdatePostponed = true; + m_postponedFiles.insert(document->fileName()); } return; } @@ -500,9 +500,9 @@ void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &docume void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) { if (!m_parserEnabled) { - if (!m_fullUpdatePostPoned) { - m_partialUpdatePostPoned = true; - m_postPonedFiles.insert(document->fileName()); + if (!m_fullUpdatePostponed) { + m_partialUpdatePostponed = true; + m_postponedFiles.insert(document->fileName()); } return; } @@ -549,34 +549,34 @@ bool TestCodeParser::postponed(const QStringList &fileList) case PartialParse: // partial is running, postponing a full parse if (fileList.isEmpty()) { - m_partialUpdatePostPoned = false; - m_postPonedFiles.clear(); - m_fullUpdatePostPoned = true; + m_partialUpdatePostponed = false; + m_postponedFiles.clear(); + m_fullUpdatePostponed = true; } else { // partial parse triggered, but full parse is postponed already, ignoring this - if (m_fullUpdatePostPoned) + if (m_fullUpdatePostponed) return true; // partial parse triggered, postpone or add current files to already postponed partial foreach (const QString &file, fileList) - m_postPonedFiles.insert(file); - m_partialUpdatePostPoned = true; + m_postponedFiles.insert(file); + m_partialUpdatePostponed = true; } return true; case FullParse: // full parse is running, postponing another full parse if (fileList.isEmpty()) { - m_partialUpdatePostPoned = false; - m_postPonedFiles.clear(); - m_fullUpdatePostPoned = true; + m_partialUpdatePostponed = false; + m_postponedFiles.clear(); + m_fullUpdatePostponed = true; } else { // full parse already postponed, ignoring triggering a partial parse - if (m_fullUpdatePostPoned) { + if (m_fullUpdatePostponed) { return true; } // partial parse triggered, postpone or add current files to already postponed partial foreach (const QString &file, fileList) - m_postPonedFiles.insert(file); - m_partialUpdatePostPoned = true; + m_postponedFiles.insert(file); + m_partialUpdatePostponed = true; } return true; case Disabled: @@ -590,14 +590,14 @@ void TestCodeParser::scanForTests(const QStringList &fileList) if (m_parserState == Disabled) { m_dirty = true; if (fileList.isEmpty()) { - m_fullUpdatePostPoned = true; - m_partialUpdatePostPoned = false; - m_postPonedFiles.clear(); + m_fullUpdatePostponed = true; + m_partialUpdatePostponed = false; + m_postponedFiles.clear(); } else { - if (!m_fullUpdatePostPoned) { - m_partialUpdatePostPoned = true; + if (!m_fullUpdatePostponed) { + m_partialUpdatePostponed = true; foreach (const QString &file, fileList) - m_postPonedFiles.insert(file); + m_postponedFiles.insert(file); } } return; @@ -725,14 +725,14 @@ void TestCodeParser::onAllTasksFinished(Core::Id type) if (type != CppTools::Constants::TASK_INDEX) return; m_parserEnabled = true; - if (m_fullUpdatePostPoned) + if (m_fullUpdatePostponed) updateTestTree(); - else if (m_partialUpdatePostPoned) { - m_partialUpdatePostPoned = false; + else if (m_partialUpdatePostponed) { + m_partialUpdatePostponed = false; QStringList tmp; - foreach (const QString &file, m_postPonedFiles) + foreach (const QString &file, m_postponedFiles) tmp << file; - m_postPonedFiles.clear(); + m_postponedFiles.clear(); scanForTests(tmp); } } @@ -757,18 +757,18 @@ void TestCodeParser::onFinished() void TestCodeParser::onPartialParsingFinished() { - QTC_ASSERT(m_fullUpdatePostPoned != m_partialUpdatePostPoned - || ((m_fullUpdatePostPoned || m_partialUpdatePostPoned) == false), - m_partialUpdatePostPoned = false;m_postPonedFiles.clear();); - if (m_fullUpdatePostPoned) { - m_fullUpdatePostPoned = false; + QTC_ASSERT(m_fullUpdatePostponed != m_partialUpdatePostponed + || ((m_fullUpdatePostponed || m_partialUpdatePostponed) == false), + m_partialUpdatePostponed = false;m_postponedFiles.clear();); + if (m_fullUpdatePostponed) { + m_fullUpdatePostponed = false; updateTestTree(); - } else if (m_partialUpdatePostPoned) { - m_partialUpdatePostPoned = false; + } else if (m_partialUpdatePostponed) { + m_partialUpdatePostponed = false; QStringList tmp; - foreach (const QString &file, m_postPonedFiles) + foreach (const QString &file, m_postponedFiles) tmp << file; - m_postPonedFiles.clear(); + m_postponedFiles.clear(); scanForTests(tmp); } else { m_dirty = false; diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index d2785766ac8..dc313ffa298 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -110,10 +110,10 @@ private: QMap m_quickDocMap; QList m_unnamedQuickDocList; bool m_parserEnabled; - bool m_fullUpdatePostPoned; - bool m_partialUpdatePostPoned; + bool m_fullUpdatePostponed; + bool m_partialUpdatePostponed; bool m_dirty; - QSet m_postPonedFiles; + QSet m_postponedFiles; State m_parserState; }; From 690f15c1029fca5917aca3279da2c2da90dc71f3 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 27 Feb 2015 14:36:14 +0100 Subject: [PATCH 076/200] Fix names of local variables Change-Id: I853ad97ff54d28714263f1431838dbe8d71f2fe2 Reviewed-by: Oliver Wolff --- plugins/autotest/testcodeparser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index cd18623cad4..3cd3ea518af 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -289,10 +289,10 @@ static QList scanDirectoryForQuickTestQmlFiles(const QStri QFutureInterface future; QmlJS::PathsAndLanguages paths; paths.maybeInsert(Utils::FileName::fromString(srcDir), QmlJS::Dialect::Qml); - const bool dontEmitDocumentChanges = false; - const bool notOnlyTheLib = false; + const bool emitDocumentChanges = false; + const bool onlyTheLib = false; QmlJS::ModelManagerInterface::importScan(future, qmlJsMM->workingCopy(), paths, qmlJsMM, - dontEmitDocumentChanges, notOnlyTheLib); + emitDocumentChanges, onlyTheLib); const QmlJS::Snapshot snapshot = QmlJSTools::Internal::ModelManager::instance()->snapshot(); QDirIterator it(srcDir, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); From aba2844a5aecb506d97d869ccd74e8bf76393883 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 3 Mar 2015 13:12:52 +0100 Subject: [PATCH 077/200] Fix possible null-pointer access Change-Id: I609828b4656c00c1c358759f0c844ecb23157b8b Reviewed-by: David Schulz --- plugins/autotest/testtreemodel.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index e707aaa052e..eadfb74b7b3 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -620,6 +620,8 @@ void TestTreeModel::qmlFilesAndFunctionNamesForMainFile(const QString &mainFile, QList *functionNames) const { TestTreeItem *unnamed = unnamedQuickTests(); + if (!unnamed) + return; for (int i = 0; i < unnamed->childCount(); ++i) { const TestTreeItem *child = unnamed->child(i); if (child->mainFile() == mainFile) { From 535f1eec182b54011e2b32a625ba048e8e99ec98 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 3 Mar 2015 13:14:31 +0100 Subject: [PATCH 078/200] Fix removing unnamed quick tests... ...this was wrong especially when closing (the last) open project that contained unnamed quick tests. Change-Id: I6d030b6219d9f397a6ffb51a985ef4147eebec8a Reviewed-by: David Schulz Reviewed-by: Christian Stenger --- plugins/autotest/testcodeparser.cpp | 16 +++++++++------- plugins/autotest/testtreemodel.cpp | 8 ++------ plugins/autotest/testtreemodel.h | 3 +-- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 3cd3ea518af..6b2ff8d4a82 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -672,14 +672,16 @@ void TestCodeParser::removeTestsIfNecessary(const QString &fileName) emit testItemsRemoved(file, TestTreeModel::QuickTest); } // unnamed Quick Tests must be handled separately - removeUnnamedQuickTestsByName(fileName); - QSet filePaths; - QList functionNames; - if (m_model->hasUnnamedQuickTests()) { - m_model->qmlFilesAndFunctionNamesForMainFile(fileName, &filePaths, &functionNames); - foreach (const QString &file, filePaths) - emit testItemsRemoved(file, TestTreeModel::QuickTest); + if (fileName.endsWith(QLatin1String(".qml"))) { + removeUnnamedQuickTestsByName(fileName); + emit unnamedQuickTestsRemoved(fileName); + } else { + m_model->qmlFilesForMainFile(fileName, &filePaths); + foreach (const QString &file, filePaths) { + removeUnnamedQuickTestsByName(file); + emit unnamedQuickTestsRemoved(file); + } } } } diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index eadfb74b7b3..2ae5693febf 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -615,19 +615,15 @@ QString TestTreeModel::getMainFileForUnnamedQuickTest(const QString &qmlFile) co return QString(); } -void TestTreeModel::qmlFilesAndFunctionNamesForMainFile(const QString &mainFile, - QSet *filePaths, - QList *functionNames) const +void TestTreeModel::qmlFilesForMainFile(const QString &mainFile, QSet *filePaths) const { TestTreeItem *unnamed = unnamedQuickTests(); if (!unnamed) return; for (int i = 0; i < unnamed->childCount(); ++i) { const TestTreeItem *child = unnamed->child(i); - if (child->mainFile() == mainFile) { + if (child->mainFile() == mainFile) filePaths->insert(child->filePath()); - functionNames->append(child->name()); - } } } diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 437aa787bec..b476bb1a5bf 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -72,8 +72,7 @@ public: QList getAllTestCases() const; QList getSelectedTests() const; QString getMainFileForUnnamedQuickTest(const QString &qmlFile) const; - void qmlFilesAndFunctionNamesForMainFile(const QString &mainFile, QSet *filePaths, - QList *functionNames) const; + void qmlFilesForMainFile(const QString &mainFile, QSet *filePaths) const; QList getUnnamedQuickTestFunctions() const; QSet qmlFilesForProFile(const QString &proFile) const; bool hasUnnamedQuickTests() const; From 36a8265549b2cbd6dd9f5b1730137428521595f7 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 3 Mar 2015 15:01:09 +0100 Subject: [PATCH 079/200] Move variable declaration into using block Change-Id: Ibf5f5fd825b7beb2bb6b607c8b822b4dfeebfda5 Reviewed-by: David Schulz --- plugins/autotest/testcodeparser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 6b2ff8d4a82..bc28fa07206 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -672,11 +672,11 @@ void TestCodeParser::removeTestsIfNecessary(const QString &fileName) emit testItemsRemoved(file, TestTreeModel::QuickTest); } // unnamed Quick Tests must be handled separately - QSet filePaths; if (fileName.endsWith(QLatin1String(".qml"))) { removeUnnamedQuickTestsByName(fileName); emit unnamedQuickTestsRemoved(fileName); } else { + QSet filePaths; m_model->qmlFilesForMainFile(fileName, &filePaths); foreach (const QString &file, filePaths) { removeUnnamedQuickTestsByName(file); From 2c1a0119bd56be2e18250e4c08c1fb201f541885 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 9 Mar 2015 10:57:40 +0100 Subject: [PATCH 080/200] Fix unexpected parser state when parsing finishes While parsing test code it might happen that the user closes all related widgets and so the parser falls into the state Disabled. This was unexpected and did print a warning. Now this case is somewhat expected and won't print a warning anymore. Change-Id: I0082bdc31f6ed351cf1dbd7b34da2f5672aee3dd Reviewed-by: Nikolai Kosjar Reviewed-by: Christian Stenger --- plugins/autotest/testcodeparser.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index bc28fa07206..2ffe2a137e3 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -751,8 +751,11 @@ void TestCodeParser::onFinished() emit parsingFinished(); m_dirty = false; break; + case Disabled: // can happen if all Test related widgets become hidden while parsing + emit parsingFinished(); + break; default: - qWarning("I should not be here..."); + qWarning("I should not be here... State: %d", m_parserState); break; } } From adb40d4bd56e7378210a32fdc4f1f63ae21f9183 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 19 Mar 2015 16:02:40 +0100 Subject: [PATCH 081/200] Fix scroll behavior of results pane For long output it should be possible to scroll across the output instead of scrolling itemwise and being never capable to view the bottom of the output. Change-Id: Ia3478932894fc0b08e10466ec987f12295e9fff5 Reviewed-by: David Schulz --- plugins/autotest/testresultspane.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 6b50fd5fd63..a19daad9d8e 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -73,6 +73,7 @@ TestResultsPane::TestResultsPane(QObject *parent) : outputLayout->addWidget(m_summaryWidget); m_listView = new Utils::ListView(m_outputWidget); + m_listView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); m_model = new TestResultModel(this); m_filterModel = new TestResultFilterModel(m_model, this); m_filterModel->setDynamicSortFilter(true); From d0de2fdbbc10a916567e1fc332f307e64f18e306 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 18 Mar 2015 16:11:00 +0100 Subject: [PATCH 082/200] Fix results output for long output For non-selected output use elided text if necessary and for selected add additional line breaks to make sure the text fits into the width of the output area. Additionally removed different style of lines coming after the first one as it does not make sense at all. Change-Id: Ifdd8cb076151ce3e0d895c702921d8f4d2a2b15a Reviewed-by: David Schulz --- plugins/autotest/testresultdelegate.cpp | 38 ++++++++++--------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp index 32aa33df5e3..51226270e73 100644 --- a/plugins/autotest/testresultdelegate.cpp +++ b/plugins/autotest/testresultdelegate.cpp @@ -119,25 +119,16 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op output = output.split(QLatin1Char('\n')).first(); } - QColor mix; - mix.setRgb( static_cast(0.7 * foreground.red() + 0.3 * background.red()), - static_cast(0.7 * foreground.green() + 0.3 * background.green()), - static_cast(0.7 * foreground.blue() + 0.3 * background.blue())); - if (selected) { int height = 0; int leading = fm.leading(); - int firstLineBreak = output.indexOf(QLatin1Char('\n')); + int fontHeight = fm.height(); output.replace(QLatin1Char('\n'), QChar::LineSeparator); QTextLayout tl(output); - if (firstLineBreak != -1) { - QTextLayout::FormatRange fr; - fr.start = firstLineBreak; - fr.length = output.length() - firstLineBreak; - fr.format.setFontStyleHint(QFont::Monospace); - fr.format.setForeground(mix); - tl.setAdditionalFormats(QList() << fr); - } + tl.setFont(painter->font()); + QTextOption txtOption; + txtOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); + tl.setTextOption(txtOption); tl.beginLayout(); while (true) { QTextLine tLine = tl.createLine(); @@ -146,18 +137,14 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op tLine.setLineWidth(positions.textAreaWidth()); height += leading; tLine.setPosition(QPoint(0, height)); - height += fm.ascent() + fm.descent(); + height += fontHeight; } tl.endLayout(); tl.draw(painter, QPoint(positions.textAreaLeft(), positions.top())); - - painter->setPen(mix); - - int bottomLine = positions.top() + fm.ascent() + height + leading; - painter->drawText(positions.textAreaLeft(), bottomLine, testResult.fileName()); } else { painter->setClipRect(positions.textArea()); - painter->drawText(positions.textAreaLeft(), positions.top() + fm.ascent(), output); + painter->drawText(positions.textAreaLeft(), positions.top() + fm.ascent(), + fm.elidedText(output, Qt::ElideRight, positions.textAreaWidth())); } QString file = testResult.fileName(); @@ -236,18 +223,23 @@ QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo int height = 0; int leading = fm.leading(); QTextLayout tl(output); + tl.setFont(opt.font); + QTextOption txtOption; + txtOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); + tl.setTextOption(txtOption); tl.beginLayout(); while (true) { QTextLine line = tl.createLine(); if (!line.isValid()) break; + line.setLineWidth(positions.textAreaWidth()); height += leading; line.setPosition(QPoint(0, height)); - height += fm.ascent() + fm.descent(); + height += fontHeight; } tl.endLayout(); - s.setHeight(height + leading + 3 + (testResult.fileName().isEmpty() ? 0 : fontHeight)); + s.setHeight(height + 3); } else { s.setHeight(fontHeight + 3); } From 377408b1b05df5dbc9ed9584408ac9750a81fb33 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 30 Mar 2015 10:44:54 +0200 Subject: [PATCH 083/200] Fix parser state handling... ...especially state transitions that may happen while project files are evaluated or source files are parsed. Change-Id: Iceef38500b6d6a4deb430738e5e960077f8eb39a Reviewed-by: David Schulz --- plugins/autotest/testcodeparser.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 2ffe2a137e3..df147835a53 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -87,6 +87,9 @@ ProjectExplorer::Project *currentProject() void TestCodeParser::setState(State state) { m_parserState = state; + // avoid triggering parse before code model parsing has finished + if (!m_parserEnabled) + return; if (m_parserState == Disabled) { m_fullUpdatePostponed = m_partialUpdatePostponed = false; m_postponedFiles.clear(); @@ -727,6 +730,9 @@ void TestCodeParser::onAllTasksFinished(Core::Id type) if (type != CppTools::Constants::TASK_INDEX) return; m_parserEnabled = true; + // avoid illegal parser state if respective widgets became hidden while parsing + if (m_parserState == Disabled) + m_parserState = Idle; if (m_fullUpdatePostponed) updateTestTree(); else if (m_partialUpdatePostponed) { @@ -888,6 +894,9 @@ void TestCodeParser::onProFileEvaluated() QStringList files; foreach (auto projectFile, p->files) files.append(projectFile.path); + // avoid illegal parser state when respective widgets became hidden while evaluating + if (m_parserState == Disabled) + m_parserState = Idle; scanForTests(files); } } From 91677381795e0f261c286ef6c5170702362c826b Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 30 Mar 2015 07:47:07 +0200 Subject: [PATCH 084/200] Add shortcuts to Run Tests options Change-Id: Ia738420baeb51940865c59b66908068c85d658c1 Reviewed-by: Riitta-Leena Miettinen Reviewed-by: David Schulz --- plugins/autotest/autotestconstants.h | 4 +- plugins/autotest/autotestplugin.cpp | 58 +++++++++++++++++++---- plugins/autotest/autotestplugin.h | 3 ++ plugins/autotest/testnavigationwidget.cpp | 25 ++-------- plugins/autotest/testnavigationwidget.h | 2 - 5 files changed, 60 insertions(+), 32 deletions(-) diff --git a/plugins/autotest/autotestconstants.h b/plugins/autotest/autotestconstants.h index d1ed6590791..ed9c4951493 100644 --- a/plugins/autotest/autotestconstants.h +++ b/plugins/autotest/autotestconstants.h @@ -25,7 +25,9 @@ namespace Autotest { namespace Constants { -const char ACTION_ID[] = "AutoTest.Action"; +const char ACTION_SCAN_ID[] = "AutoTest.ScanAction"; +const char ACTION_RUN_ALL_ID[] = "AutoTest.RunAll"; +const char ACTION_RUN_SELECTED_ID[] = "AutoTest.RunSelected"; const char MENU_ID[] = "AutoTest.Menu"; const char AUTOTEST_ID[] = "AutoTest.ATP"; const char AUTOTEST_CONTEXT[] = "Auto Tests"; diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index 581ed8a195e..724841f025c 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -52,6 +52,7 @@ #endif using namespace Autotest::Internal; +using namespace Core; static AutotestPlugin *m_instance = 0; @@ -101,17 +102,32 @@ bool AutotestPlugin::checkLicense() void AutotestPlugin::initializeMenuEntries() { - QAction *action = new QAction(tr("Re&scan Tests"), this); - Core::Command *command = Core::ActionManager::registerAction(action, Constants::ACTION_ID, - Core::Context(Core::Constants::C_GLOBAL)); + ActionContainer *menu = ActionManager::createMenu(Constants::MENU_ID); + menu->menu()->setTitle(tr("Tests")); + + QAction *action = new QAction(tr("Run &All Tests"), this); + Command *command = ActionManager::registerAction(action, Constants::ACTION_RUN_ALL_ID); + command->setDefaultKeySequence(QKeySequence(tr("Alt+Shift+T,Alt+A"))); + connect(action, &QAction::triggered, + this, &AutotestPlugin::onRunAllTriggered); + menu->addAction(command); + + action = new QAction(tr("&Run Selected Tests"), this); + command = ActionManager::registerAction(action, Constants::ACTION_RUN_SELECTED_ID); + command->setDefaultKeySequence(QKeySequence(tr("Alt+Shift+T,Alt+R"))); + connect(action, &QAction::triggered, + this, &AutotestPlugin::onRunSelectedTriggered); + menu->addAction(command); + + action = new QAction(tr("Re&scan Tests"), this); + command = ActionManager::registerAction(action, Constants::ACTION_SCAN_ID); command->setDefaultKeySequence(QKeySequence(tr("Alt+Shift+T,Alt+S"))); connect(action, &QAction::triggered, TestTreeModel::instance()->parser(), &TestCodeParser::updateTestTree); - - Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::MENU_ID); - menu->menu()->setTitle(tr("Tests")); menu->addAction(command); - Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu); + + ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu); + connect(menu->menu(), &QMenu::aboutToShow, this, &AutotestPlugin::updateMenuItemsEnabledState); } bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorString) @@ -124,7 +140,7 @@ bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorStri initializeMenuEntries(); - m_settings->fromSettings(Core::ICore::settings()); + m_settings->fromSettings(ICore::settings()); addAutoReleasedObject(new TestSettingsPage(m_settings)); addAutoReleasedObject(new TestNavigationWidgetFactory); addAutoReleasedObject(TestResultsPane::instance()); @@ -141,6 +157,32 @@ ExtensionSystem::IPlugin::ShutdownFlag AutotestPlugin::aboutToShutdown() return SynchronousShutdown; } +void AutotestPlugin::onRunAllTriggered() +{ + TestRunner *runner = TestRunner::instance(); + TestTreeModel *model = TestTreeModel::instance(); + runner->setSelectedTests(model->getAllTestCases()); + runner->runTests(); +} + +void AutotestPlugin::onRunSelectedTriggered() +{ + TestRunner *runner = TestRunner::instance(); + TestTreeModel *model = TestTreeModel::instance(); + runner->setSelectedTests(model->getSelectedTests()); + runner->runTests(); +} + +void AutotestPlugin::updateMenuItemsEnabledState() +{ + const bool enabled = !TestRunner::instance()->isTestRunning(); + const bool hasTests = TestTreeModel::instance()->hasTests(); + + ActionManager::command(Constants::ACTION_RUN_ALL_ID)->action()->setEnabled(enabled && hasTests); + ActionManager::command(Constants::ACTION_RUN_SELECTED_ID)->action()->setEnabled(enabled && hasTests); + ActionManager::command(Constants::ACTION_SCAN_ID)->action()->setEnabled(enabled); +} + QList AutotestPlugin::createTestObjects() const { QList tests; diff --git a/plugins/autotest/autotestplugin.h b/plugins/autotest/autotestplugin.h index 8bf2664b40b..b7a02d89e77 100644 --- a/plugins/autotest/autotestplugin.h +++ b/plugins/autotest/autotestplugin.h @@ -49,6 +49,9 @@ public: private: bool checkLicense(); void initializeMenuEntries(); + void onRunAllTriggered(); + void onRunSelectedTriggered(); + void updateMenuItemsEnabledState(); QList createTestObjects() const; const QSharedPointer m_settings; }; diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index e23ebb5c885..dea7b97874d 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -88,19 +89,15 @@ void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event) const bool enabled = !TestRunner::instance()->isTestRunning(); const bool hasTests = m_model->hasTests(); QMenu menu; - QAction *runAll = new QAction(tr("Run All Tests"), &menu); - QAction *runSelected = new QAction(tr("Run Selected Tests"), &menu); + QAction *runAll = Core::ActionManager::command(Constants::ACTION_RUN_ALL_ID)->action(); + QAction *runSelected = Core::ActionManager::command(Constants::ACTION_RUN_SELECTED_ID)->action(); QAction *selectAll = new QAction(tr("Select All"), &menu); QAction *deselectAll = new QAction(tr("Deselect All"), &menu); // TODO remove? - QAction *rescan = new QAction(tr("Rescan"), &menu); + QAction *rescan = Core::ActionManager::command(Constants::ACTION_SCAN_ID)->action(); - connect(runAll, &QAction::triggered, this, &TestNavigationWidget::onRunAllTriggered); - connect(runSelected, &QAction::triggered, this, &TestNavigationWidget::onRunSelectedTriggered); connect(selectAll, &QAction::triggered, m_view, &TestTreeView::selectAll); connect(deselectAll, &QAction::triggered, m_view, &TestTreeView::deselectAll); - connect(rescan, &QAction::triggered, TestTreeModel::instance()->parser(), - &TestCodeParser::updateTestTree); runAll->setEnabled(enabled && hasTests); runSelected->setEnabled(enabled && hasTests); @@ -165,20 +162,6 @@ void TestNavigationWidget::onItemActivated(const QModelIndex &index) } } -void TestNavigationWidget::onRunAllTriggered() -{ - TestRunner *runner = TestRunner::instance(); - runner->setSelectedTests(m_model->getAllTestCases()); - runner->runTests(); -} - -void TestNavigationWidget::onRunSelectedTriggered() -{ - TestRunner *runner = TestRunner::instance(); - runner->setSelectedTests(m_model->getSelectedTests()); - runner->runTests(); -} - void TestNavigationWidget::onSortClicked() { if (m_sortAlphabetically) { diff --git a/plugins/autotest/testnavigationwidget.h b/plugins/autotest/testnavigationwidget.h index 5e0ec2197ef..a4b4c6f0610 100644 --- a/plugins/autotest/testnavigationwidget.h +++ b/plugins/autotest/testnavigationwidget.h @@ -62,8 +62,6 @@ public slots: private slots: void onItemActivated(const QModelIndex &index); - void onRunAllTriggered(); - void onRunSelectedTriggered(); void onSortClicked(); void onFilterMenuTriggered(QAction *action); void onParsingStarted(); From dbf11d4520ba188415f469ca4e1713c7e0412225 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 30 Mar 2015 12:56:21 +0200 Subject: [PATCH 085/200] Set TARGET for application to project name Change-Id: I12ed1df61cf364c6c390f8196f2f6174fe098aee Reviewed-by: Robert Loehning --- shared/autotest/src.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/autotest/src.pro b/shared/autotest/src.pro index 3d0e33848b6..26f9b3a1523 100644 --- a/shared/autotest/src.pro +++ b/shared/autotest/src.pro @@ -6,5 +6,6 @@ CONFIG -= app_bundle @endif TEMPLATE = app +TARGET = %ProjectName% SOURCES += main.%CppSourceSuffix% From ae7b3e84047e25f86f7d9cfefb55e39fd421ee5f Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Mon, 30 Mar 2015 13:56:50 +0200 Subject: [PATCH 086/200] Autotest: edit UI text and messages Fix capitalization, punctuation, and grammar issues. Change-Id: Ie5044a1a3445ea078fe52ae20b1b4eec747e3de4 Reviewed-by: Christian Stenger --- plugins/autotest/testnavigationwidget.cpp | 4 ++-- plugins/autotest/testresultspane.cpp | 2 +- plugins/autotest/testrunner.cpp | 24 +++++++++++------------ plugins/autotest/testsettingspage.ui | 24 +++++++++++------------ plugins/autotest/testtreemodel.cpp | 5 ++--- plugins/autotest/testxmloutputreader.cpp | 10 +++++----- 6 files changed, 34 insertions(+), 35 deletions(-) diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index dea7b97874d..df2f0dcdd04 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -196,13 +196,13 @@ void TestNavigationWidget::onParsingFinished() void TestNavigationWidget::initializeFilterMenu() { QAction *action = new QAction(m_filterMenu); - action->setText(tr("Show init and cleanup functions")); + action->setText(tr("Show Init and Cleanup Functions")); action->setCheckable(true); action->setChecked(false); action->setData(TestTreeSortFilterModel::ShowInitAndCleanup); m_filterMenu->addAction(action); action = new QAction(m_filterMenu); - action->setText(tr("Show data functions")); + action->setText(tr("Show Data Functions")); action->setCheckable(true); action->setChecked(false); action->setData(TestTreeSortFilterModel::ShowTestData); diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index a19daad9d8e..feace48f7ce 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -324,7 +324,7 @@ void TestResultsPane::initializeFilterMenu() void TestResultsPane::updateSummaryLabel() { - QString labelText = QString::fromLatin1("

Test Summary:   %1 %2, %3 %4") + QString labelText = QString::fromLatin1("

Test summary:   %1 %2, %3 %4") .arg(QString::number(m_model->resultTypeCount(Result::PASS)), tr("passes"), QString::number(m_model->resultTypeCount(Result::FAIL)), tr("fails")); int count = m_model->resultTypeCount(Result::UNEXPECTED_PASS); diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 6b1c68a9d4e..29e5476ce35 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -139,7 +139,7 @@ void performTestRun(QFutureInterface &futureInterface, QString commandFilePath = executableFilePath(testConfiguration->targetFile(), environment); if (commandFilePath.isEmpty()) { emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, - QObject::tr("*** Could not find command '%1' ***").arg(testConfiguration->targetFile()))); + QObject::tr("Could not find command \"%1\".").arg(testConfiguration->targetFile()))); continue; } @@ -166,7 +166,7 @@ void performTestRun(QFutureInterface &futureInterface, testProcess.kill(); testProcess.waitForFinished(); emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, - QObject::tr("*** Test Run canceled by user ***"))); + QObject::tr("Test run canceled by user."))); } qApp->processEvents(); } @@ -177,7 +177,7 @@ void performTestRun(QFutureInterface &futureInterface, testProcess.kill(); testProcess.waitForFinished(); emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, QObject::tr( - "*** Test Case canceled due to timeout ***\nMaybe raise the timeout?"))); + "Test case canceled due to timeout. \nMaybe raise the timeout?"))); } } } @@ -200,13 +200,13 @@ void TestRunner::runTests() if (!config->project()) { toBeRemoved.append(config); TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, - tr("*** Project is null for '%1' - removing from Test Run ***\n" - "This might be the case for a faulty environment or similar." + tr("Project is null for \"%1\". Removing from test run.\n" + "Check the test environment." ).arg(config->displayName()))); } if (displayRunConfigWarnings && config->guessedConfiguration()) { TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, - tr("*** Project's run configuration was guessed for '%1' ***\n" + tr("Project's run configuration was guessed for \"%1\".\n" "This might cause trouble during execution.").arg(config->displayName()))); } } @@ -217,16 +217,16 @@ void TestRunner::runTests() if (m_selectedTests.empty()) { TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, - tr("*** No tests selected - canceling Test Run ***"))); + tr("No tests selected. Canceling test run."))); return; } ProjectExplorer::Project *project = m_selectedTests.at(0)->project(); if (!project) { TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, - tr("*** Project is null - canceling Test Run ***\n" - "Actually only Desktop kits are supported - make sure the " - "current active kit is a Desktop kit."))); + tr("Project is null. Canceling test run.\n" + "Only desktop kits are supported. Make sure the " + "currently active kit is a desktop kit."))); return; } @@ -235,7 +235,7 @@ void TestRunner::runTests() if (projectExplorerSettings.buildBeforeDeploy) { if (!project->hasActiveBuildSettings()) { TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_FATAL, - tr("*** Project is not configured - canceling Test Run ***"))); + tr("Project is not configured. Canceling test run."))); return; } buildProject(project); @@ -245,7 +245,7 @@ void TestRunner::runTests() if (!m_buildSucceeded) { TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_FATAL, - tr("*** Build failed - canceling Test Run ***"))); + tr("Build failed. Canceling test run."))); return; } } diff --git a/plugins/autotest/testsettingspage.ui b/plugins/autotest/testsettingspage.ui index 164f9f7f5c1..b7154268835 100644 --- a/plugins/autotest/testsettingspage.ui +++ b/plugins/autotest/testsettingspage.ui @@ -32,7 +32,7 @@ - Timeout used when executing test cases. This will apply for each test case on its own, not the whole project. + Timeout used when executing each test case. Timeout: @@ -83,10 +83,10 @@ - If checked Internal Messages won't be shown by default. (You can still enable them on the test results filter) + Hides internal messages by default. You can still enable them by using the test results filter. - Omit Internal Messages + Omit internal messages true @@ -96,10 +96,10 @@ - If checked Warnings regarding a guessed Run Configuration won't be shown. + Hides warnings related to a guessed run configuration. - Omit Run Configuration Warnings + Omit run configuration warnings @@ -161,7 +161,7 @@ - Use Walltime metrics for executing benchmarks. (default) + Uses walltime metrics for executing benchmarks (default). Walltime @@ -180,10 +180,10 @@ - Use tick counter for executing benchmarks. + Uses tick counter when executing benchmarks. - Tickcounter + Tick counter @@ -196,10 +196,10 @@ - Use event counter when executing benchmarks. + Uses event counter when executing benchmarks. - Eventcounter + Event counter @@ -215,7 +215,7 @@ - Use callgrind when executing benchmark. (valgrind must be installed) + Uses Valgrind Callgrind when executing benchmarks (it must be installed). Callgrind @@ -234,7 +234,7 @@ - Use perf when executing benchmarks. (perf must be installed) + Uses Perf when executing benchmarks (it must be installed). Perf diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 2ae5693febf..5bba6b7c3c3 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -213,9 +213,8 @@ QVariant TestTreeModel::data(const QModelIndex &index, int role) const switch(role) { case Qt::ToolTipRole: if (item->type() == TestTreeItem::TEST_CLASS && item->name().isEmpty()) - return tr("

Unnamed test cases can't be (un)checked - avoid this by assigning a name." - "
Having unnamed test cases invalidates the check state of named test " - "cases with the same main.cpp when executing selected tests.

"); + return tr("

Give all test cases a name to ensure correct behavior " + "when running test cases and to be able to select them.

"); return item->filePath(); case Qt::DecorationRole: return testTreeIcon(item->type()); diff --git a/plugins/autotest/testxmloutputreader.cpp b/plugins/autotest/testxmloutputreader.cpp index 31d21b959ad..fb71f56881e 100644 --- a/plugins/autotest/testxmloutputreader.cpp +++ b/plugins/autotest/testxmloutputreader.cpp @@ -191,7 +191,7 @@ void TestXmlOutputReader::processOutput() lineNumber = 0; readingDescription = false; testResultCreated(TestResult(QString(), QString(), QString(), Result::MESSAGE_CURRENT_TEST, - QObject::tr("Entering Test Function %1::%2").arg(className).arg(testCase))); + QObject::tr("Entering test function %1::%2").arg(className).arg(testCase))); continue; } if (xmlStartsWith(line, QLatin1String("") && !duration.isEmpty()) { TestResult testResult(className, testCase, QString(), Result::MESSAGE_INTERNAL, - QObject::tr("execution took %1ms").arg(duration)); + QObject::tr("Execution took %1 ms.").arg(duration)); testResultCreated(testResult); emit increaseProgress(); } else if (line == QLatin1String("") && !duration.isEmpty()) { TestResult testResult(className, QString(), QString(), Result::MESSAGE_INTERNAL, - QObject::tr("Test execution took %1ms").arg(duration)); + QObject::tr("Test execution took %1 ms.").arg(duration)); testResultCreated(testResult); } else if (readingDescription) { if (line.endsWith(QLatin1String("]]>"))) { @@ -250,10 +250,10 @@ void TestXmlOutputReader::processOutput() } } else if (xmlStartsWith(line, QLatin1String(""), qtVersion)) { testResultCreated(FaultyTestResult(Result::MESSAGE_INTERNAL, - QObject::tr("Qt Version: %1").arg(qtVersion))); + QObject::tr("Qt version: %1").arg(qtVersion))); } else if (xmlStartsWith(line, QLatin1String(""), qtestVersion)) { testResultCreated(FaultyTestResult(Result::MESSAGE_INTERNAL, - QObject::tr("QTest Version: %1").arg(qtestVersion))); + QObject::tr("QTest version: %1").arg(qtestVersion))); } else { // qDebug() << "Unhandled line:" << line; // TODO remove } From 3f506a2a36af1c62d370f8d2ba9c4e492be15432 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 30 Mar 2015 15:32:13 +0200 Subject: [PATCH 087/200] Allow filtering of test results always This almost reverts 8bb03409353be640a18b58dd80e1bb67f96f13fe. Change-Id: I57ac2e1dd052ce434f7381f4d6df52ecdc68fed6 Reviewed-by: David Schulz --- plugins/autotest/testresultmodel.cpp | 14 ++++++-------- plugins/autotest/testresultmodel.h | 2 -- plugins/autotest/testresultspane.cpp | 10 ---------- plugins/autotest/testresultspane.h | 1 - 4 files changed, 6 insertions(+), 21 deletions(-) diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index 07040014885..ee104700326 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -114,12 +114,13 @@ QVariant TestResultModel::data(const QModelIndex &index, int role) const void TestResultModel::addTestResult(const TestResult &testResult) { const bool isCurrentTestMssg = testResult.result() == Result::MESSAGE_CURRENT_TEST; - const bool hasCurrentTestMssg = m_availableResultTypes.contains(Result::MESSAGE_CURRENT_TEST); + TestResult lastMssg = m_testResults.empty() ? TestResult() : m_testResults.last(); int position = m_testResults.size(); - if (hasCurrentTestMssg && isCurrentTestMssg) { - m_testResults.last().setDescription(testResult.description()); + if (isCurrentTestMssg && lastMssg.result() == Result::MESSAGE_CURRENT_TEST) { + lastMssg.setDescription(testResult.description()); + m_testResults.replace(m_testResults.size() - 1, lastMssg); const QModelIndex changed = index(m_testResults.size() - 1, 0, QModelIndex()); emit dataChanged(changed, changed); } else { @@ -134,17 +135,15 @@ void TestResultModel::addTestResult(const TestResult &testResult) int count = m_testResultCount.value(testResult.result(), 0); m_testResultCount.insert(testResult.result(), ++count); } - - m_availableResultTypes.insert(testResult.result()); } void TestResultModel::removeCurrentTestMessage() { - if (m_availableResultTypes.contains(Result::MESSAGE_CURRENT_TEST)) { + TestResult lastMssg = m_testResults.empty() ? TestResult() : m_testResults.last(); + if (lastMssg.result() == Result::MESSAGE_CURRENT_TEST) { beginRemoveRows(QModelIndex(), m_testResults.size() - 1, m_testResults.size() - 1); m_testResults.removeLast(); endRemoveRows(); - m_availableResultTypes.remove(Result::MESSAGE_CURRENT_TEST); } } @@ -159,7 +158,6 @@ void TestResultModel::clearTestResults() m_maxWidthOfFileName = 0; m_widthOfLineNumber = 0; endRemoveRows(); - m_availableResultTypes.clear(); } TestResult TestResultModel::testResult(const QModelIndex &index) const diff --git a/plugins/autotest/testresultmodel.h b/plugins/autotest/testresultmodel.h index c10bc44013d..97f3a3a53ce 100644 --- a/plugins/autotest/testresultmodel.h +++ b/plugins/autotest/testresultmodel.h @@ -52,7 +52,6 @@ public: int maxWidthOfFileName(const QFont &font); int maxWidthOfLineNumber(const QFont &font); - bool hasResultType(Result::Type type) { return m_availableResultTypes.contains(type); } int resultTypeCount(Result::Type type); signals: @@ -66,7 +65,6 @@ private: int m_maxWidthOfFileName; int m_lastMaxWidthIndex; QFont m_measurementFont; - QSet m_availableResultTypes; }; class TestResultFilterModel : public QSortFilterProxyModel diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index feace48f7ce..45fe7fa0674 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -120,7 +120,6 @@ void TestResultsPane::createToolButtons() m_filterButton->setPopupMode(QToolButton::InstantPopup); m_filterMenu = new QMenu(m_filterButton); initializeFilterMenu(); - connect(m_filterMenu, &QMenu::aboutToShow, this, &TestResultsPane::updateFilterMenu); connect(m_filterMenu, &QMenu::triggered, this, &TestResultsPane::filterMenuTriggered); m_filterButton->setMenu(m_filterMenu); } @@ -349,15 +348,6 @@ void TestResultsPane::updateSummaryLabel() m_summaryLabel->setText(labelText); } -void TestResultsPane::updateFilterMenu() -{ - foreach (QAction *action, m_filterMenu->actions()) { - if (action->isCheckable()) - action->setEnabled(m_model->hasResultType( - TestResult::toResultType(action->data().value()))); - } -} - void TestResultsPane::enableAllFilter() { foreach (QAction *action, m_filterMenu->actions()) { diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h index e2d7c6746fa..ac097dde94d 100644 --- a/plugins/autotest/testresultspane.h +++ b/plugins/autotest/testresultspane.h @@ -78,7 +78,6 @@ private slots: void onItemActivated(const QModelIndex &index); void onRunAllTriggered(); void onRunSelectedTriggered(); - void updateFilterMenu(); void enableAllFilter(); void filterMenuTriggered(QAction *action); From 2182b2adbebee6c3fdf5f68fc417d244e4801238 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 2 Apr 2015 14:55:37 +0200 Subject: [PATCH 088/200] Change ui string to avoid confused users Change-Id: I431de718d01e454bb55216afd5d0ca792fa69677 Reviewed-by: Riitta-Leena Miettinen --- plugins/autotest/testcodeparser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index df147835a53..71e5eaff6d7 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -638,7 +638,7 @@ void TestCodeParser::scanForTests(const QStringList &fileList) QFuture future = QtConcurrent::run(&performParse, list, this); Core::FutureProgress *progress = Core::ProgressManager::addTask(future, isFullParse ? tr("Scanning for Tests") - : tr("Updating Tests"), + : tr("Refreshing Tests List"), Autotest::Constants::TASK_PARSE); connect(progress, &Core::FutureProgress::finished, this, &TestCodeParser::onFinished); From d43a36c8167a37903f70b49b67ec39efa0ba086e Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 2 Apr 2015 12:16:55 +0200 Subject: [PATCH 089/200] Trigger parse when project parts have been updated Change-Id: I8b81bd91671b3d855c617c63185baa2951a55e6e Reviewed-by: David Schulz --- plugins/autotest/testcodeparser.cpp | 7 +++++++ plugins/autotest/testcodeparser.h | 1 + plugins/autotest/testtreemodel.cpp | 2 ++ 3 files changed, 10 insertions(+) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 71e5eaff6d7..c3ae634b598 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -538,6 +538,13 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) } } +void TestCodeParser::onProjectPartsUpdated(ProjectExplorer::Project *project) +{ + if (project != currentProject()) + return; + updateTestTree(); +} + void TestCodeParser::removeFiles(const QStringList &files) { foreach (const QString &file, files) diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index dc313ffa298..f4894e96742 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -83,6 +83,7 @@ public slots: void onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document); void onQmlDocumentUpdated(const QmlJS::Document::Ptr &document); + void onProjectPartsUpdated(ProjectExplorer::Project *project); void removeFiles(const QStringList &files); void onProFileEvaluated(); diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 5bba6b7c3c3..0040b4d903f 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -115,6 +115,8 @@ void TestTreeModel::enableParsing() m_parser, &TestCodeParser::onCppDocumentUpdated, Qt::QueuedConnection); connect(cppMM, &CppTools::CppModelManager::aboutToRemoveFiles, m_parser, &TestCodeParser::removeFiles, Qt::QueuedConnection); + connect(cppMM, &CppTools::CppModelManager::projectPartsUpdated, + m_parser, &TestCodeParser::onProjectPartsUpdated); QmlJS::ModelManagerInterface *qmlJsMM = QmlJS::ModelManagerInterface::instance(); connect(qmlJsMM, &QmlJS::ModelManagerInterface::documentUpdated, From 178318d077c1646d6c75788977731d7949093f2d Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 9 Apr 2015 15:11:35 +0200 Subject: [PATCH 090/200] Fix initialization order... ...to avoid accessing uninitialized members. Change-Id: I5d174d2b6f351dc5189a65c1639b0f284a1fd52d Reviewed-by: David Schulz --- plugins/autotest/testresultdelegate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/autotest/testresultdelegate.h b/plugins/autotest/testresultdelegate.h index 0627ed5ee59..8bc5d58ad86 100644 --- a/plugins/autotest/testresultdelegate.h +++ b/plugins/autotest/testresultdelegate.h @@ -56,11 +56,11 @@ private: m_top(options.rect.top()), m_bottom(options.rect.bottom()) { + m_typeAreaWidth = QFontMetrics(options.font).width(QLatin1String("XXXXXXXX")); int flexibleArea = lineAreaLeft() - textAreaLeft() - ITEM_SPACING; if (m_maxFileLength > flexibleArea / 2) m_realFileLength = flexibleArea / 2; m_fontHeight = QFontMetrics(options.font).height(); - m_typeAreaWidth = QFontMetrics(options.font).width(QLatin1String("XXXXXXXX")); } int top() const { return m_top + ITEM_MARGIN; } From 475c6cea1e5bb30b4853f389c043bb9b08770d03 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 9 Apr 2015 15:51:42 +0200 Subject: [PATCH 091/200] Limit result output by default For huge amount of output the processing takes much too long and blocks QC. So, limiting it to a reasonable value seems appropriate. Additionally provide a setting to be still able to get the full output if you need to. Change-Id: I811d69be33c77830049f64fcf291681f05011966 Reviewed-by: Riitta-Leena Miettinen Reviewed-by: David Schulz --- plugins/autotest/testresultdelegate.cpp | 17 ++++++++++++++++- plugins/autotest/testsettings.cpp | 9 +++++++-- plugins/autotest/testsettings.h | 1 + plugins/autotest/testsettingspage.cpp | 2 ++ plugins/autotest/testsettingspage.ui | 15 ++++++++++++++- 5 files changed, 40 insertions(+), 4 deletions(-) diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp index 51226270e73..86a12323a7d 100644 --- a/plugins/autotest/testresultdelegate.cpp +++ b/plugins/autotest/testresultdelegate.cpp @@ -17,8 +17,10 @@ ** ****************************************************************************/ +#include "autotestplugin.h" #include "testresultdelegate.h" #include "testresultmodel.h" +#include "testsettings.h" #include #include @@ -28,6 +30,8 @@ namespace Autotest { namespace Internal { +const static int outputLimit = 100000; + TestResultDelegate::TestResultDelegate(QObject *parent) : QStyledItemDelegate(parent) { @@ -124,6 +128,11 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op int leading = fm.leading(); int fontHeight = fm.height(); output.replace(QLatin1Char('\n'), QChar::LineSeparator); + + if (AutotestPlugin::instance()->settings()->limitResultOutput + && output.length() > outputLimit) + output = output.left(outputLimit).append(QLatin1String("...")); + QTextLayout tl(output); tl.setFont(painter->font()); QTextOption txtOption; @@ -143,8 +152,9 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op tl.draw(painter, QPoint(positions.textAreaLeft(), positions.top())); } else { painter->setClipRect(positions.textArea()); + // cut output before generating elided text as this takes quite long for exhaustive output painter->drawText(positions.textAreaLeft(), positions.top() + fm.ascent(), - fm.elidedText(output, Qt::ElideRight, positions.textAreaWidth())); + fm.elidedText(output.left(2000), Qt::ElideRight, positions.textAreaWidth())); } QString file = testResult.fileName(); @@ -222,6 +232,11 @@ QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo int height = 0; int leading = fm.leading(); + + if (AutotestPlugin::instance()->settings()->limitResultOutput + && output.length() > outputLimit) + output = output.left(outputLimit).append(QLatin1String("...")); + QTextLayout tl(output); tl.setFont(opt.font); QTextOption txtOption; diff --git a/plugins/autotest/testsettings.cpp b/plugins/autotest/testsettings.cpp index 06567842157..3a11b8c66b9 100644 --- a/plugins/autotest/testsettings.cpp +++ b/plugins/autotest/testsettings.cpp @@ -29,10 +29,12 @@ static const char timeoutKey[] = "Timeout"; static const char metricsKey[] = "Metrics"; static const char omitInternalKey[] = "OmitInternal"; static const char omitRunConfigWarnKey[] = "OmitRCWarnings"; +static const char limitResultOutputKey[] = "LimitResultOutput"; static const int defaultTimeout = 60000; TestSettings::TestSettings() - : timeout(defaultTimeout), metrics(Walltime), omitInternalMssg(true), omitRunConfigWarn(false) + : timeout(defaultTimeout), metrics(Walltime), omitInternalMssg(true), omitRunConfigWarn(false), + limitResultOutput(true) { } @@ -43,6 +45,7 @@ void TestSettings::toSettings(QSettings *s) const s->setValue(QLatin1String(metricsKey), metrics); s->setValue(QLatin1String(omitInternalKey), omitInternalMssg); s->setValue(QLatin1String(omitRunConfigWarnKey), omitRunConfigWarn); + s->setValue(QLatin1String(limitResultOutputKey), limitResultOutput); s->endGroup(); } @@ -71,13 +74,15 @@ void TestSettings::fromSettings(const QSettings *s) metrics = intToMetrics(s->value(root + QLatin1String(metricsKey), Walltime).toInt()); omitInternalMssg = s->value(root + QLatin1String(omitInternalKey), true).toBool(); omitRunConfigWarn = s->value(root + QLatin1String(omitRunConfigWarnKey), false).toBool(); + limitResultOutput = s->value(root + QLatin1String(limitResultOutputKey), true).toBool(); } bool TestSettings::equals(const TestSettings &rhs) const { return timeout == rhs.timeout && metrics == rhs.metrics && omitInternalMssg == rhs.omitInternalMssg - && omitRunConfigWarn == rhs.omitRunConfigWarn; + && omitRunConfigWarn == rhs.omitRunConfigWarn + && limitResultOutput == rhs.limitResultOutput; } QString TestSettings::metricsTypeToOption(const MetricsType type) diff --git a/plugins/autotest/testsettings.h b/plugins/autotest/testsettings.h index c7ff22c3ff2..520edde6fc6 100644 --- a/plugins/autotest/testsettings.h +++ b/plugins/autotest/testsettings.h @@ -49,6 +49,7 @@ struct TestSettings MetricsType metrics; bool omitInternalMssg; bool omitRunConfigWarn; + bool limitResultOutput; }; inline bool operator==(const TestSettings &s1, const TestSettings &s2) { return s1.equals(s2); } diff --git a/plugins/autotest/testsettingspage.cpp b/plugins/autotest/testsettingspage.cpp index 53ab2c71a10..e65bff754a4 100644 --- a/plugins/autotest/testsettingspage.cpp +++ b/plugins/autotest/testsettingspage.cpp @@ -41,6 +41,7 @@ void TestSettingsWidget::setSettings(const TestSettings &settings) m_ui.timeoutSpin->setValue(settings.timeout / 1000); // we store milliseconds m_ui.omitInternalMsgCB->setChecked(settings.omitInternalMssg); m_ui.omitRunConfigWarnCB->setChecked(settings.omitRunConfigWarn); + m_ui.limitResultOutputCB->setChecked(settings.limitResultOutput); switch (settings.metrics) { case MetricsType::Walltime: @@ -69,6 +70,7 @@ TestSettings TestSettingsWidget::settings() const result.timeout = m_ui.timeoutSpin->value() * 1000; // we display seconds result.omitInternalMssg = m_ui.omitInternalMsgCB->isChecked(); result.omitRunConfigWarn = m_ui.omitRunConfigWarnCB->isChecked(); + result.limitResultOutput = m_ui.limitResultOutputCB->isChecked(); if (m_ui.walltimeRB->isChecked()) result.metrics = MetricsType::Walltime; diff --git a/plugins/autotest/testsettingspage.ui b/plugins/autotest/testsettingspage.ui index b7154268835..bc3c6f6b0c5 100644 --- a/plugins/autotest/testsettingspage.ui +++ b/plugins/autotest/testsettingspage.ui @@ -13,7 +13,7 @@ Form - + 9 @@ -103,6 +103,19 @@ + + + + Limit result output to 100000 characters. + + + Limit result output + + + true + + + From 97a8806417af7ed048d7dd0f2ea07098d64bd99f Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 10 Apr 2015 11:22:39 +0200 Subject: [PATCH 092/200] Don't reset class name for empty lines. Change-Id: Ib8ae9244bb282a10f1696de8f82469474fb0498d Reviewed-by: Christian Stenger --- plugins/autotest/testxmloutputreader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/autotest/testxmloutputreader.cpp b/plugins/autotest/testxmloutputreader.cpp index fb71f56881e..d8b3400d6b1 100644 --- a/plugins/autotest/testxmloutputreader.cpp +++ b/plugins/autotest/testxmloutputreader.cpp @@ -176,12 +176,12 @@ void TestXmlOutputReader::processOutput() while (m_testApplication->canReadLine()) { // TODO Qt5 uses UTF-8 - while Qt4 uses ISO-8859-1 - could this be a problem? const QString line = QString::fromUtf8(m_testApplication->readLine()).trimmed(); - if (line.isEmpty() || line.startsWith(QLatin1String(" Date: Fri, 10 Apr 2015 09:35:41 +0200 Subject: [PATCH 093/200] Fix parsing of encoded xml attributes If an xml attribute contains an entity parsing it failed due to missing decoding. This patch decodes entities holding (hexa-)decimal entities. This is especially necessary for files (or paths) containing some special characters that might end up encoded inside the output that would be generated by running the tests. Change-Id: I4f3b9f9edc59ff1433b92ed4ce1933eaf29ffe74 Reviewed-by: David Schulz --- plugins/autotest/testxmloutputreader.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/plugins/autotest/testxmloutputreader.cpp b/plugins/autotest/testxmloutputreader.cpp index d8b3400d6b1..8d0fa72235d 100644 --- a/plugins/autotest/testxmloutputreader.cpp +++ b/plugins/autotest/testxmloutputreader.cpp @@ -20,7 +20,7 @@ #include "testxmloutputreader.h" #include "testresult.h" -#include +#include #include #include #include @@ -28,6 +28,25 @@ namespace Autotest { namespace Internal { +static QString decode(const QString& original) +{ + QString result(original); + static QRegExp regex(QLatin1String("&#((x[0-9A-F]+)|([0-9]+));"), Qt::CaseInsensitive); + regex.setMinimal(true); + + int pos = 0; + while ((pos = regex.indexIn(original, pos)) != -1) { + const QString value = regex.cap(1); + if (value.startsWith(QLatin1Char('x'))) + result.replace(regex.cap(0), QChar(value.mid(1).toInt(0, 16))); + else + result.replace(regex.cap(0), QChar(value.toInt(0, 10))); + pos += regex.matchedLength(); + } + + return result; +} + static bool xmlStartsWith(const QString &code, const QString &start, QString &result) { if (code.startsWith(start)) { @@ -57,7 +76,7 @@ static bool xmlExtractTypeFileLine(const QString &code, const QString &tagStart, result = TestResult::resultFromString( code.mid(start, code.indexOf(QLatin1Char('"'), start) - start)); start = code.indexOf(QLatin1String(" file=\"")) + 7; - file = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start); + file = decode(code.mid(start, code.indexOf(QLatin1Char('"'), start) - start)); start = code.indexOf(QLatin1String(" line=\"")) + 7; line = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start).toInt(); return true; From f1b240d004578d54b6497a910098566022c8edb0 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 10 Apr 2015 15:09:45 +0200 Subject: [PATCH 094/200] Disable context menu entries while parsing Change-Id: Ib562ed00065fedd94fdaed0edb11b0fa62a18de5 Reviewed-by: David Schulz --- plugins/autotest/testcodeparser.h | 1 + plugins/autotest/testnavigationwidget.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index f4894e96742..1b8215fe507 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -55,6 +55,7 @@ public: explicit TestCodeParser(TestTreeModel *parent = 0); virtual ~TestCodeParser(); void setState(State state); + State state() const { return m_parserState; } #ifdef WITH_TESTS int autoTestsCount() const; diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index df2f0dcdd04..f9847a57827 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -86,7 +86,8 @@ TestNavigationWidget::~TestNavigationWidget() void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event) { - const bool enabled = !TestRunner::instance()->isTestRunning(); + const bool enabled = !TestRunner::instance()->isTestRunning() + && m_model->parser()->state() == TestCodeParser::Idle; const bool hasTests = m_model->hasTests(); QMenu menu; QAction *runAll = Core::ActionManager::command(Constants::ACTION_RUN_ALL_ID)->action(); From 7768f07ece949d17e552a29f2199db14dce273ea Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 10 Apr 2015 14:33:44 +0200 Subject: [PATCH 095/200] Add wizard install step when building with qbs Change-Id: I83249c99b7a70b6dbb6909446dbe9c7e89b163fc Reviewed-by: Christian Kandeler --- plugins/autotest/autotest.qbs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/plugins/autotest/autotest.qbs b/plugins/autotest/autotest.qbs index 8b522b6eb62..93505bce3ba 100644 --- a/plugins/autotest/autotest.qbs +++ b/plugins/autotest/autotest.qbs @@ -77,4 +77,15 @@ QtcPlugin { "autotestunittests.qrc", ] } + + Group { + name: "Auto Test Wizard" + prefix: "../../shared/autotest/" + files: [ + "*" + ] + fileTags: [] + qbs.install: true + qbs.installDir: project.ide_data_path + "/templates/wizards/autotest" + } } From a1e8cc5e44b8ab4bb5e78ec4a6fe08615038c0ae Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 10 Apr 2015 13:15:34 +0200 Subject: [PATCH 096/200] Use only active target for guessing run environment Change-Id: Id7f9f299a22dabd350ac1e8279500cf1054210f8 Reviewed-by: Tobias Hunger --- plugins/autotest/testtreemodel.cpp | 32 ++++++++++-------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 0040b4d903f..732b229534c 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -411,28 +411,16 @@ static void addProjectInformation(TestConfiguration *config, const QString &file // if we could not figure out the run configuration // try to use the run configuration of the parent project if (!hasDesktopTarget && targetProject && !targetFile.isEmpty()) { - QList rcs = target->runConfigurations(); - foreach (ProjectExplorer::RunConfiguration *rc, rcs) { - ProjectExplorer::LocalApplicationRunConfiguration *localRunConfiguration - = qobject_cast(rc); - if (localRunConfiguration) { - if (ProjectExplorer::ProjectNode *localRootProjectNode = targetProject->rootProjectNode()) { - QList localFileNodes = localRootProjectNode->fileNodes(); - if (localFileNodes.size()) { - if (localFileNodes.at(0)->path() - == targetProject->projectFilePath()) { - hasDesktopTarget = true; - workDir = Utils::FileUtils::normalizePathName( - localRunConfiguration->workingDirectory()); - ProjectExplorer::EnvironmentAspect *environmentAspect - = localRunConfiguration->extraAspect(); - env = environmentAspect->environment(); - guessedRunConfiguration = true; - break; - } - } - } - } + auto localRunConfiguration + = qobject_cast(target->activeRunConfiguration()); + if (localRunConfiguration) { + hasDesktopTarget = true; + workDir = Utils::FileUtils::normalizePathName( + localRunConfiguration->workingDirectory()); + ProjectExplorer::EnvironmentAspect *environmentAspect + = localRunConfiguration->extraAspect(); + env = environmentAspect->environment(); + guessedRunConfiguration = true; } } } From b88bfbb55a8e50c9ddaef9f7e803658009c0df6f Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 14 Apr 2015 15:24:31 +0200 Subject: [PATCH 097/200] Fix state handling of parser... ...and enable/disable respective menu items accordingly. Now it should be impossible to trigger more than one parse at a time or setting a state and invalidating a state with higher priority. Change-Id: I0bcbeca6626209918e0a74b0bd2722583fc47bb3 Reviewed-by: David Schulz --- plugins/autotest/autotestplugin.cpp | 9 ++++++--- plugins/autotest/testcodeparser.cpp | 14 +++++++++----- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index 724841f025c..a2ab7834187 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -126,8 +126,10 @@ void AutotestPlugin::initializeMenuEntries() TestTreeModel::instance()->parser(), &TestCodeParser::updateTestTree); menu->addAction(command); - ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu); - connect(menu->menu(), &QMenu::aboutToShow, this, &AutotestPlugin::updateMenuItemsEnabledState); + ActionContainer *toolsMenu = ActionManager::actionContainer(Core::Constants::M_TOOLS); + toolsMenu->addMenu(menu); + connect(toolsMenu->menu(), &QMenu::aboutToShow, + this, &AutotestPlugin::updateMenuItemsEnabledState); } bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorString) @@ -175,7 +177,8 @@ void AutotestPlugin::onRunSelectedTriggered() void AutotestPlugin::updateMenuItemsEnabledState() { - const bool enabled = !TestRunner::instance()->isTestRunning(); + const bool enabled = !TestRunner::instance()->isTestRunning() + && TestTreeModel::instance()->parser()->state() == TestCodeParser::Idle; const bool hasTests = TestTreeModel::instance()->hasTests(); ActionManager::command(Constants::ACTION_RUN_ALL_ID)->action()->setEnabled(enabled && hasTests); diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index c3ae634b598..8c0b7b43d7b 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -86,10 +86,15 @@ ProjectExplorer::Project *currentProject() void TestCodeParser::setState(State state) { - m_parserState = state; // avoid triggering parse before code model parsing has finished if (!m_parserEnabled) return; + + if ((state == Disabled || state == Idle) + && (m_parserState == PartialParse || m_parserState == FullParse)) + return; + m_parserState = state; + if (m_parserState == Disabled) { m_fullUpdatePostponed = m_partialUpdatePostponed = false; m_postponedFiles.clear(); @@ -738,8 +743,8 @@ void TestCodeParser::onAllTasksFinished(Core::Id type) return; m_parserEnabled = true; // avoid illegal parser state if respective widgets became hidden while parsing - if (m_parserState == Disabled) - m_parserState = Idle; + setState(Idle); + if (m_fullUpdatePostponed) updateTestTree(); else if (m_partialUpdatePostponed) { @@ -902,8 +907,7 @@ void TestCodeParser::onProFileEvaluated() foreach (auto projectFile, p->files) files.append(projectFile.path); // avoid illegal parser state when respective widgets became hidden while evaluating - if (m_parserState == Disabled) - m_parserState = Idle; + setState(Idle); scanForTests(files); } } From 00ca77a560021c332b3d6f76efb79d082e930da0 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 15 Apr 2015 09:30:28 +0200 Subject: [PATCH 098/200] Do not allow triggering multiple test runs at once This was possible as triggering further test runs could happen while the current test run was still building the project. Additionally it's now possible to stop the build process (if any) by hitting the Stop button of the test results pane as this is part of the test run. Change-Id: I38940b5b8f4ba9e373785921c04cbceaeb2e5acf Reviewed-by: David Schulz --- plugins/autotest/testrunner.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 29e5476ce35..07f90a56ad1 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -191,6 +191,9 @@ void TestRunner::runTests() const QString metricsOption = TestSettings::metricsTypeToOption(settings->metrics); const bool displayRunConfigWarnings = !settings->omitRunConfigWarn; + m_executingTests = true; + emit testRunStarted(); + // clear old log and output pane TestResultsPane::instance()->clearContents(); @@ -218,6 +221,7 @@ void TestRunner::runTests() if (m_selectedTests.empty()) { TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, tr("No tests selected. Canceling test run."))); + onFinished(); return; } @@ -227,6 +231,7 @@ void TestRunner::runTests() tr("Project is null. Canceling test run.\n" "Only desktop kits are supported. Make sure the " "currently active kit is a desktop kit."))); + onFinished(); return; } @@ -236,27 +241,33 @@ void TestRunner::runTests() if (!project->hasActiveBuildSettings()) { TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_FATAL, tr("Project is not configured. Canceling test run."))); + onFinished(); return; } + + auto connection = connect(this, &TestRunner::requestStopTestRun, [&] () { + ProjectExplorer::BuildManager::instance()->cancel(); + m_building = false; + m_buildSucceeded = false; + }); buildProject(project); while (m_building) { qApp->processEvents(); } + disconnect(connection); if (!m_buildSucceeded) { TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_FATAL, tr("Build failed. Canceling test run."))); + onFinished(); return; } } - m_executingTests = true; connect(this, &TestRunner::testResultCreated, TestResultsPane::instance(), &TestResultsPane::addTestResult, Qt::QueuedConnection); - emit testRunStarted(); - QFuture future = QtConcurrent::run(&performTestRun, m_selectedTests, timeout, metricsOption, this); Core::FutureProgress *progress = Core::ProgressManager::addTask(future, tr("Running Tests"), Autotest::Constants::TASK_INDEX); @@ -268,8 +279,7 @@ void TestRunner::buildProject(ProjectExplorer::Project *project) { m_building = true; m_buildSucceeded = false; - ProjectExplorer::BuildManager *buildManager = static_cast( - ProjectExplorer::BuildManager::instance()); + ProjectExplorer::BuildManager *buildManager = ProjectExplorer::BuildManager::instance(); connect(buildManager, &ProjectExplorer::BuildManager::buildQueueFinished, this, &TestRunner::buildFinished); ProjectExplorer::ProjectExplorerPlugin::buildProject(project); @@ -277,8 +287,7 @@ void TestRunner::buildProject(ProjectExplorer::Project *project) void TestRunner::buildFinished(bool success) { - ProjectExplorer::BuildManager *buildManager = static_cast( - ProjectExplorer::BuildManager::instance()); + ProjectExplorer::BuildManager *buildManager = ProjectExplorer::BuildManager::instance(); disconnect(buildManager, &ProjectExplorer::BuildManager::buildQueueFinished, this, &TestRunner::buildFinished); m_building = false; From 7a8b73a0caf0d3ede1b81049ae05b3ffdd51e71d Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 15 Apr 2015 09:34:11 +0200 Subject: [PATCH 099/200] Fix enabling and disabling test code parser Change-Id: If03752aaf3db36929e5e9d1b468e691e4dab1b96 Reviewed-by: David Schulz --- plugins/autotest/testtreemodel.cpp | 4 +++- plugins/autotest/testtreemodel.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 732b229534c..2ee021ad06b 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -102,6 +102,7 @@ TestTreeModel::~TestTreeModel() void TestTreeModel::enableParsing() { + m_refCounter.ref(); m_parser->setState(TestCodeParser::Idle); if (m_connectionsInitialized) return; @@ -128,7 +129,8 @@ void TestTreeModel::enableParsing() void TestTreeModel::disableParsing() { - m_parser->setState(TestCodeParser::Disabled); + if (!m_refCounter.deref()) + m_parser->setState(TestCodeParser::Disabled); } QModelIndex TestTreeModel::index(int row, int column, const QModelIndex &parent) const diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index b476bb1a5bf..15a00ecb387 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -112,6 +112,7 @@ private: TestTreeItem *m_quickTestRootItem; TestCodeParser *m_parser; bool m_connectionsInitialized; + QAtomicInt m_refCounter; }; class TestTreeSortFilterModel : public QSortFilterProxyModel From c13c37f9f414e253a777ee8a1d38de1ac8679b52 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 16 Apr 2015 15:07:56 +0200 Subject: [PATCH 100/200] Fix plugin unit test Since d43a36c8167a37903f70b49b67ec39efa0ba086e the code parser could have been internally triggered already while still evaluating the project. This made the parser trigger a parsingFinished() already for a parse where not the full project had been available inside the code model which made the plugin unit test fail. Change-Id: I6cc787c24205cb82c6c2636f79bd0acc5c778c64 Reviewed-by: David Schulz --- plugins/autotest/testcodeparser.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 8c0b7b43d7b..004f733fbda 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -547,7 +547,10 @@ void TestCodeParser::onProjectPartsUpdated(ProjectExplorer::Project *project) { if (project != currentProject()) return; - updateTestTree(); + if (!m_parserEnabled || m_parserState == Disabled) + m_fullUpdatePostponed = true; + else + emitUpdateTestTree(); } void TestCodeParser::removeFiles(const QStringList &files) From fcf8484eb2e827936b93479fa8d773a66c574759 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 21 Apr 2015 07:41:06 +0200 Subject: [PATCH 101/200] Replace ListView by TreeView inside results pane This removes the flickering of the view when adding too many items in a short time frame. Additionally it is the first step towards making the results a real tree for having a better overview and to be able to reduce the output easier to what is wanted by the user. Change-Id: Id515bf0f43c5037d956bdbf2818a5d6ef97c82dd Reviewed-by: David Schulz --- plugins/autotest/testresultdelegate.cpp | 4 +++ plugins/autotest/testresultspane.cpp | 37 +++++++++++++------------ plugins/autotest/testresultspane.h | 4 +-- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp index 86a12323a7d..c20ce112007 100644 --- a/plugins/autotest/testresultdelegate.cpp +++ b/plugins/autotest/testresultdelegate.cpp @@ -46,6 +46,8 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op { QStyleOptionViewItemV4 opt = option; initStyleOption(&opt, index); + // make sure we paint the complete delegate instead of keeping an offset + opt.rect.adjust(-opt.rect.x(), 0, 0, 0); painter->save(); QFontMetrics fm(opt.font); @@ -181,6 +183,8 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItemV4 opt = option; + // make sure opt.rect is initialized correctly - otherwise we might get a width of 0 + opt.initFrom(opt.widget); initStyleOption(&opt, index); const QAbstractItemView *view = qobject_cast(opt.widget); diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 45fe7fa0674..e53af910da2 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -72,21 +72,22 @@ TestResultsPane::TestResultsPane(QObject *parent) : outputLayout->addWidget(m_summaryWidget); - m_listView = new Utils::ListView(m_outputWidget); - m_listView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + m_treeView = new Utils::TreeView(m_outputWidget); + m_treeView->setHeaderHidden(true); + m_treeView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); m_model = new TestResultModel(this); m_filterModel = new TestResultFilterModel(m_model, this); m_filterModel->setDynamicSortFilter(true); - m_listView->setModel(m_filterModel); + m_treeView->setModel(m_filterModel); TestResultDelegate *trd = new TestResultDelegate(this); - m_listView->setItemDelegate(trd); + m_treeView->setItemDelegate(trd); - outputLayout->addWidget(m_listView); + outputLayout->addWidget(m_treeView); createToolButtons(); - connect(m_listView, &Utils::ListView::activated, this, &TestResultsPane::onItemActivated); - connect(m_listView->selectionModel(), &QItemSelectionModel::currentChanged, + connect(m_treeView, &Utils::TreeView::activated, this, &TestResultsPane::onItemActivated); + connect(m_treeView->selectionModel(), &QItemSelectionModel::currentChanged, trd, &TestResultDelegate::currentChanged); connect(TestRunner::instance(), &TestRunner::testRunStarted, this, &TestResultsPane::onTestRunStarted); @@ -96,23 +97,23 @@ TestResultsPane::TestResultsPane(QObject *parent) : void TestResultsPane::createToolButtons() { - m_runAll = new QToolButton(m_listView); + m_runAll = new QToolButton(m_treeView); m_runAll->setIcon(QIcon(QLatin1String(":/images/run.png"))); m_runAll->setToolTip(tr("Run All Tests")); connect(m_runAll, &QToolButton::clicked, this, &TestResultsPane::onRunAllTriggered); - m_runSelected = new QToolButton(m_listView); + m_runSelected = new QToolButton(m_treeView); m_runSelected->setIcon(QIcon(QLatin1String(":/images/runselected.png"))); m_runSelected->setToolTip(tr("Run Selected Tests")); connect(m_runSelected, &QToolButton::clicked, this, &TestResultsPane::onRunSelectedTriggered); - m_stopTestRun = new QToolButton(m_listView); + m_stopTestRun = new QToolButton(m_treeView); m_stopTestRun->setIcon(QIcon(QLatin1String(":/images/stop.png"))); m_stopTestRun->setToolTip(tr("Stop Test Run")); m_stopTestRun->setEnabled(false); connect(m_stopTestRun, &QToolButton::clicked, TestRunner::instance(), &TestRunner::requestStopTestRun); - m_filterButton = new QToolButton(m_listView); + m_filterButton = new QToolButton(m_treeView); m_filterButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_FILTER))); m_filterButton->setToolTip(tr("Filter Test Results")); m_filterButton->setProperty("noArrow", true); @@ -135,14 +136,14 @@ TestResultsPane *TestResultsPane::instance() TestResultsPane::~TestResultsPane() { - delete m_listView; + delete m_treeView; m_instance = 0; } void TestResultsPane::addTestResult(const TestResult &result) { m_model->addTestResult(result); - if (!m_listView->isVisible()) + if (!m_treeView->isVisible()) popup(Core::IOutputPane::NoModeSwitch); flash(); navigateStateChanged(); @@ -205,7 +206,7 @@ void TestResultsPane::setFocus() bool TestResultsPane::hasFocus() const { - return m_listView->hasFocus(); + return m_treeView->hasFocus(); } bool TestResultsPane::canFocus() const @@ -233,7 +234,7 @@ void TestResultsPane::goToNext() if (!canNext()) return; - QModelIndex currentIndex = m_listView->currentIndex(); + QModelIndex currentIndex = m_treeView->currentIndex(); if (currentIndex.isValid()) { int row = currentIndex.row() + 1; if (row == m_filterModel->rowCount(QModelIndex())) @@ -242,7 +243,7 @@ void TestResultsPane::goToNext() } else { currentIndex = m_filterModel->index(0, 0, QModelIndex()); } - m_listView->setCurrentIndex(currentIndex); + m_treeView->setCurrentIndex(currentIndex); onItemActivated(currentIndex); } @@ -251,7 +252,7 @@ void TestResultsPane::goToPrev() if (!canPrevious()) return; - QModelIndex currentIndex = m_listView->currentIndex(); + QModelIndex currentIndex = m_treeView->currentIndex(); if (currentIndex.isValid()) { int row = currentIndex.row() - 1; if (row < 0) @@ -260,7 +261,7 @@ void TestResultsPane::goToPrev() } else { currentIndex = m_filterModel->index(m_filterModel->rowCount(QModelIndex()) - 1, 0, QModelIndex()); } - m_listView->setCurrentIndex(currentIndex); + m_treeView->setCurrentIndex(currentIndex); onItemActivated(currentIndex); } diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h index ac097dde94d..0d76c56ff48 100644 --- a/plugins/autotest/testresultspane.h +++ b/plugins/autotest/testresultspane.h @@ -36,7 +36,7 @@ class IContext; } namespace Utils { -class ListView; +class TreeView; } namespace Autotest { @@ -93,7 +93,7 @@ private: QWidget *m_outputWidget; QFrame *m_summaryWidget; QLabel *m_summaryLabel; - Utils::ListView *m_listView; + Utils::TreeView *m_treeView; TestResultModel *m_model; TestResultFilterModel *m_filterModel; Core::IContext *m_context; From d3f1d9a3fd907408fa2f02aee42fa8abd06bd223 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 6 May 2015 09:34:36 +0200 Subject: [PATCH 102/200] Fix creating auto test without gui Change-Id: Id1d0b686eda09f6fb513374c9b5337ffdd83b82a Reviewed-by: Eike Ziller --- shared/autotest/src.pro | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/shared/autotest/src.pro b/shared/autotest/src.pro index 26f9b3a1523..61fbe2a5bcf 100644 --- a/shared/autotest/src.pro +++ b/shared/autotest/src.pro @@ -1,7 +1,9 @@ @if "%RequireGUI%" == "true" -QT += gui widgets +QT += core gui +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @else -QT += console +QT -= gui +CONFIG += console CONFIG -= app_bundle @endif From fa28f1cb303d79ff3feb1416ef0637785dade8fc Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Mon, 18 May 2015 14:55:47 +0200 Subject: [PATCH 103/200] Disable run buttons until tests are found Change-Id: I418b63dbdd4a641fa02a61b792ec6dbfafe39749 Reviewed-by: Christian Stenger --- plugins/autotest/testresultspane.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index e53af910da2..c2a2b5851f6 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -100,11 +100,13 @@ void TestResultsPane::createToolButtons() m_runAll = new QToolButton(m_treeView); m_runAll->setIcon(QIcon(QLatin1String(":/images/run.png"))); m_runAll->setToolTip(tr("Run All Tests")); + m_runAll->setEnabled(false); connect(m_runAll, &QToolButton::clicked, this, &TestResultsPane::onRunAllTriggered); m_runSelected = new QToolButton(m_treeView); m_runSelected->setIcon(QIcon(QLatin1String(":/images/runselected.png"))); m_runSelected->setToolTip(tr("Run Selected Tests")); + m_runSelected->setEnabled(false); connect(m_runSelected, &QToolButton::clicked, this, &TestResultsPane::onRunSelectedTriggered); m_stopTestRun = new QToolButton(m_treeView); From 5b93689702d45025b4b36cf65c807be21eeb3c05 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 19 May 2015 07:41:39 +0200 Subject: [PATCH 104/200] Detect special functions for Quick Tests Quick Tests are capable of having benchmarks, data driven tests and special functions (init/cleanup/...) as well. Change-Id: Ieb9b6b1f842f1211a9d3192b486f789c987fa27b Reviewed-by: David Schulz --- plugins/autotest/testvisitor.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/plugins/autotest/testvisitor.cpp b/plugins/autotest/testvisitor.cpp index b43a0c02712..2d38cb56b4c 100644 --- a/plugins/autotest/testvisitor.cpp +++ b/plugins/autotest/testvisitor.cpp @@ -34,6 +34,12 @@ namespace Autotest { namespace Internal { +// names of special functions (applies for QTest as well as Quick Tests) +static QList specialFunctions = QList() << QLatin1String("initTestCase") + << QLatin1String("cleanupTestCase") + << QLatin1String("init") + << QLatin1String("cleanup"); + /************************** Cpp Test Symbol Visitor ***************************/ TestVisitor::TestVisitor(const QString &fullQualifiedClassName) @@ -45,11 +51,6 @@ TestVisitor::~TestVisitor() { } -static QList specialFunctions = QList() << QLatin1String("initTestCase") - << QLatin1String("cleanupTestCase") - << QLatin1String("init") - << QLatin1String("cleanup"); - bool TestVisitor::visit(CPlusPlus::Class *symbol) { const CPlusPlus::Overview o; @@ -177,13 +178,21 @@ bool TestQmlVisitor::visit(QmlJS::AST::UiScriptBinding *ast) bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast) { const QStringRef name = ast->name; - if (name.startsWith(QLatin1String("test_"))) { + if (name.startsWith(QLatin1String("test_")) + || name.startsWith(QLatin1String("benchmark_")) + || name.endsWith(QLatin1String("_data")) + || specialFunctions.contains(name.toString())) { const auto sourceLocation = ast->firstSourceLocation(); TestCodeLocationAndType locationAndType; locationAndType.m_fileName = m_currentDoc->fileName(); locationAndType.m_line = sourceLocation.startLine; locationAndType.m_column = sourceLocation.startColumn - 1; - locationAndType.m_type = TestTreeItem::TEST_FUNCTION; + if (specialFunctions.contains(name.toString())) + locationAndType.m_type = TestTreeItem::TEST_SPECIALFUNCTION; + else if (name.endsWith(QLatin1String("_data"))) + locationAndType.m_type = TestTreeItem::TEST_DATAFUNCTION; + else + locationAndType.m_type = TestTreeItem::TEST_FUNCTION; m_testFunctions.insert(name.toString(), locationAndType); } From c5fad3756006429026165a345b9eadcd4b5425df Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 19 May 2015 11:00:45 +0200 Subject: [PATCH 105/200] Avoid null pointer access Change-Id: Ie6f64a97d1d97efaa1e1f3ea784a119981159e62 Reviewed-by: David Schulz --- plugins/autotest/testtreemodel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 2ee021ad06b..134a9dc2141 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -598,7 +598,8 @@ QList TestTreeModel::getSelectedTests() const QString TestTreeModel::getMainFileForUnnamedQuickTest(const QString &qmlFile) const { const TestTreeItem *unnamed = unnamedQuickTests(); - for (int row = 0, count = unnamed->childCount(); row < count; ++row) { + const int count = unnamed ? unnamed->childCount() : 0; + for (int row = 0; row < count; ++row) { const TestTreeItem *child = unnamed->child(row); if (qmlFile == child->filePath()) return child->mainFile(); From 36824fe498b74c9379689fb35be609b60b1edb2a Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Tue, 5 May 2015 14:16:53 +0200 Subject: [PATCH 106/200] .gitignore user setting files Change-Id: I414032475ce1d8f76150809b1dbd3871b6e91763 Reviewed-by: Christian Stenger --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..be7521b7545 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +# qtcreator generated files +*.pro.user* +*.qbs.user* From 21afdf227aeec4a5d4cfe8d32588cce25d0e4cf5 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 29 May 2015 11:30:23 +0200 Subject: [PATCH 107/200] Fix wrong state of Run/Run All buttons Introduced with fa28f1cb303d79ff3feb1416ef0637785dade8fc Change-Id: I80f5e08bcf2b630fcf7a4a77d47db6e7b7d26e50 Reviewed-by: Robert Loehning --- plugins/autotest/testresultspane.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index c2a2b5851f6..3d9e874bdf5 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -190,6 +190,8 @@ void TestResultsPane::visibilityChanged(bool visible) return; connect(TestTreeModel::instance(), &TestTreeModel::testTreeModelChanged, this, &TestResultsPane::onTestTreeModelChanged); + // make sure run/run all are in correct state + onTestTreeModelChanged(); m_wasVisibleBefore = true; TestTreeModel::instance()->enableParsing(); } else { From f092ad0a2ef4e7c6b8230a5289c25725ff47bcdd Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Fri, 29 May 2015 13:45:35 +0200 Subject: [PATCH 108/200] Simplify TestResultsPane::visibilityChanged Change-Id: Ie278384bb0fe899989a01a0ad89455b11059787f Reviewed-by: Christian Stenger --- plugins/autotest/testresultspane.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 3d9e874bdf5..0d6b9052b84 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -185,23 +185,20 @@ void TestResultsPane::clearContents() void TestResultsPane::visibilityChanged(bool visible) { + if (visible == m_wasVisibleBefore) + return; if (visible) { - if (m_wasVisibleBefore) - return; connect(TestTreeModel::instance(), &TestTreeModel::testTreeModelChanged, this, &TestResultsPane::onTestTreeModelChanged); // make sure run/run all are in correct state onTestTreeModelChanged(); - m_wasVisibleBefore = true; TestTreeModel::instance()->enableParsing(); } else { - if (!m_wasVisibleBefore) - return; disconnect(TestTreeModel::instance(), &TestTreeModel::testTreeModelChanged, this, &TestResultsPane::onTestTreeModelChanged); - m_wasVisibleBefore = false; TestTreeModel::instance()->disableParsing(); } + m_wasVisibleBefore = visible; } void TestResultsPane::setFocus() From eeccdfbd54359d26690fdb53610cd122a12db09f Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 20 Apr 2015 13:22:01 +0200 Subject: [PATCH 109/200] Fix getting source file name on OSX If the current executable is an app bundle the source file location is given as relative path from the app bundles location instead of the "real" executable somewhere inside the app bundle. Change-Id: I37ad2daae5a7ebde65c0e76a8a9a7837401bc749 Reviewed-by: Eike Ziller --- plugins/autotest/testxmloutputreader.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/plugins/autotest/testxmloutputreader.cpp b/plugins/autotest/testxmloutputreader.cpp index 8d0fa72235d..ae6c223f933 100644 --- a/plugins/autotest/testxmloutputreader.cpp +++ b/plugins/autotest/testxmloutputreader.cpp @@ -20,6 +20,8 @@ #include "testxmloutputreader.h" #include "testresult.h" +#include + #include #include #include @@ -47,6 +49,17 @@ static QString decode(const QString& original) return result; } +static QString constructSourceFilePath(const QString &path, const QString &filePath, + const QString &app) +{ + if (Utils::HostOsInfo::isMacHost() && !app.isEmpty()) { + const QString fileName(QFileInfo(app).fileName()); + return QFileInfo(path.left(path.lastIndexOf(fileName + QLatin1String(".app"))), filePath) + .canonicalFilePath(); + } + return QFileInfo(path, filePath).canonicalFilePath(); +} + static bool xmlStartsWith(const QString &code, const QString &start, QString &result) { if (code.startsWith(start)) { @@ -229,7 +242,8 @@ void TestXmlOutputReader::processOutput() if (line.endsWith(QLatin1String("/>"))) { TestResult testResult(className, testCase, dataTag, result, description); if (!file.isEmpty()) - file = QFileInfo(m_testApplication->workingDirectory(), file).canonicalFilePath(); + file = constructSourceFilePath(m_testApplication->workingDirectory(), file, + m_testApplication->program()); testResult.setFileName(file); testResult.setLine(lineNumber); testResultCreated(testResult); @@ -244,7 +258,8 @@ void TestXmlOutputReader::processOutput() if (line == QLatin1String("") || line == QLatin1String("")) { TestResult testResult(className, testCase, dataTag, result, description); if (!file.isEmpty()) - file = QFileInfo(m_testApplication->workingDirectory(), file).canonicalFilePath(); + file = constructSourceFilePath(m_testApplication->workingDirectory(), file, + m_testApplication->program()); testResult.setFileName(file); testResult.setLine(lineNumber); testResultCreated(testResult); From 0afd504748f49ae6c6d77403fd1d6f6604b6eaa8 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 16 Apr 2015 08:54:41 +0200 Subject: [PATCH 110/200] Add auto-scroll feature for results pane Change-Id: Iff209384c2bf30b3ce2b9241ce1c719a44592e65 Reviewed-by: David Schulz Reviewed-by: Christian Stenger --- plugins/autotest/testresultspane.cpp | 18 +- plugins/autotest/testresultspane.h | 3 + plugins/autotest/testsettings.cpp | 8 +- plugins/autotest/testsettings.h | 1 + plugins/autotest/testsettingspage.cpp | 2 + plugins/autotest/testsettingspage.ui | 488 ++++++++++++-------------- 6 files changed, 256 insertions(+), 264 deletions(-) diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 0d6b9052b84..9ebb1c09fbb 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -46,7 +47,8 @@ namespace Internal { TestResultsPane::TestResultsPane(QObject *parent) : Core::IOutputPane(parent), m_context(new Core::IContext(this)), - m_wasVisibleBefore(false) + m_wasVisibleBefore(false), + m_autoScroll(false) { m_outputWidget = new QWidget; QVBoxLayout *outputLayout = new QVBoxLayout; @@ -144,6 +146,9 @@ TestResultsPane::~TestResultsPane() void TestResultsPane::addTestResult(const TestResult &result) { + const QScrollBar *scrollBar = m_treeView->verticalScrollBar(); + m_atEnd = scrollBar ? scrollBar->value() == scrollBar->maximum() : true; + m_model->addTestResult(result); if (!m_treeView->isVisible()) popup(Core::IOutputPane::NoModeSwitch); @@ -181,6 +186,9 @@ void TestResultsPane::clearContents() m_filterModel->clearTestResults(); navigateStateChanged(); m_summaryWidget->setVisible(false); + m_autoScroll = AutotestPlugin::instance()->settings()->autoScroll; + connect(m_treeView->verticalScrollBar(), &QScrollBar::rangeChanged, + this, &TestResultsPane::onScrollBarRangeChanged, Qt::UniqueConnection); } void TestResultsPane::visibilityChanged(bool visible) @@ -381,6 +389,14 @@ void TestResultsPane::onTestRunFinished() updateSummaryLabel(); m_summaryWidget->setVisible(true); m_model->removeCurrentTestMessage(); + disconnect(m_treeView->verticalScrollBar(), &QScrollBar::rangeChanged, + this, &TestResultsPane::onScrollBarRangeChanged); +} + +void TestResultsPane::onScrollBarRangeChanged(int, int max) +{ + if (m_autoScroll && m_atEnd) + m_treeView->verticalScrollBar()->setValue(max); } void TestResultsPane::onTestTreeModelChanged() diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h index 0d76c56ff48..37a35eece81 100644 --- a/plugins/autotest/testresultspane.h +++ b/plugins/autotest/testresultspane.h @@ -88,6 +88,7 @@ private: void createToolButtons(); void onTestRunStarted(); void onTestRunFinished(); + void onScrollBarRangeChanged(int, int max); void onTestTreeModelChanged(); QWidget *m_outputWidget; @@ -103,6 +104,8 @@ private: QToolButton *m_filterButton; QMenu *m_filterMenu; bool m_wasVisibleBefore; + bool m_autoScroll; + bool m_atEnd; }; } // namespace Internal diff --git a/plugins/autotest/testsettings.cpp b/plugins/autotest/testsettings.cpp index 3a11b8c66b9..bb5bcd61ece 100644 --- a/plugins/autotest/testsettings.cpp +++ b/plugins/autotest/testsettings.cpp @@ -30,11 +30,12 @@ static const char metricsKey[] = "Metrics"; static const char omitInternalKey[] = "OmitInternal"; static const char omitRunConfigWarnKey[] = "OmitRCWarnings"; static const char limitResultOutputKey[] = "LimitResultOutput"; +static const char autoScrollKey[] = "AutoScrollResults"; static const int defaultTimeout = 60000; TestSettings::TestSettings() : timeout(defaultTimeout), metrics(Walltime), omitInternalMssg(true), omitRunConfigWarn(false), - limitResultOutput(true) + limitResultOutput(true), autoScroll(true) { } @@ -46,6 +47,7 @@ void TestSettings::toSettings(QSettings *s) const s->setValue(QLatin1String(omitInternalKey), omitInternalMssg); s->setValue(QLatin1String(omitRunConfigWarnKey), omitRunConfigWarn); s->setValue(QLatin1String(limitResultOutputKey), limitResultOutput); + s->setValue(QLatin1String(autoScrollKey), autoScroll); s->endGroup(); } @@ -75,6 +77,7 @@ void TestSettings::fromSettings(const QSettings *s) omitInternalMssg = s->value(root + QLatin1String(omitInternalKey), true).toBool(); omitRunConfigWarn = s->value(root + QLatin1String(omitRunConfigWarnKey), false).toBool(); limitResultOutput = s->value(root + QLatin1String(limitResultOutputKey), true).toBool(); + autoScroll = s->value(root + QLatin1String(autoScrollKey), true).toBool(); } bool TestSettings::equals(const TestSettings &rhs) const @@ -82,7 +85,8 @@ bool TestSettings::equals(const TestSettings &rhs) const return timeout == rhs.timeout && metrics == rhs.metrics && omitInternalMssg == rhs.omitInternalMssg && omitRunConfigWarn == rhs.omitRunConfigWarn - && limitResultOutput == rhs.limitResultOutput; + && limitResultOutput == rhs.limitResultOutput + && autoScroll == rhs.autoScroll; } QString TestSettings::metricsTypeToOption(const MetricsType type) diff --git a/plugins/autotest/testsettings.h b/plugins/autotest/testsettings.h index 520edde6fc6..8ef368e8040 100644 --- a/plugins/autotest/testsettings.h +++ b/plugins/autotest/testsettings.h @@ -50,6 +50,7 @@ struct TestSettings bool omitInternalMssg; bool omitRunConfigWarn; bool limitResultOutput; + bool autoScroll; }; inline bool operator==(const TestSettings &s1, const TestSettings &s2) { return s1.equals(s2); } diff --git a/plugins/autotest/testsettingspage.cpp b/plugins/autotest/testsettingspage.cpp index e65bff754a4..cf96ef92b63 100644 --- a/plugins/autotest/testsettingspage.cpp +++ b/plugins/autotest/testsettingspage.cpp @@ -42,6 +42,7 @@ void TestSettingsWidget::setSettings(const TestSettings &settings) m_ui.omitInternalMsgCB->setChecked(settings.omitInternalMssg); m_ui.omitRunConfigWarnCB->setChecked(settings.omitRunConfigWarn); m_ui.limitResultOutputCB->setChecked(settings.limitResultOutput); + m_ui.autoScrollCB->setChecked(settings.autoScroll); switch (settings.metrics) { case MetricsType::Walltime: @@ -71,6 +72,7 @@ TestSettings TestSettingsWidget::settings() const result.omitInternalMssg = m_ui.omitInternalMsgCB->isChecked(); result.omitRunConfigWarn = m_ui.omitRunConfigWarnCB->isChecked(); result.limitResultOutput = m_ui.limitResultOutputCB->isChecked(); + result.autoScroll = m_ui.autoScrollCB->isChecked(); if (m_ui.walltimeRB->isChecked()) result.metrics = MetricsType::Walltime; diff --git a/plugins/autotest/testsettingspage.ui b/plugins/autotest/testsettingspage.ui index bc3c6f6b0c5..1822cfbbd9b 100644 --- a/plugins/autotest/testsettingspage.ui +++ b/plugins/autotest/testsettingspage.ui @@ -6,289 +6,255 @@ 0 0 - 463 - 338 + 407 + 228 Form - - - - 9 - 10 - 435 - 307 - - - - - - - - - + + + + + + + Timeout used when executing each test case. + + + Timeout: + + + + + + + Timeout used when executing test cases. This will apply for each test case on its own, not the whole project. + + + s + + + 5 + + + 36000 + + + 60 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + Benchmark Metrics + + - + + + + 0 + 0 + + - Timeout used when executing each test case. + Uses walltime metrics for executing benchmarks (default). - Timeout: + Walltime + + + true - + + + + 0 + 0 + + - Timeout used when executing test cases. This will apply for each test case on its own, not the whole project. + Uses tick counter when executing benchmarks. - - s + + Tick counter - - 5 + + + + + + + 0 + 0 + - - 36000 + + Uses event counter when executing benchmarks. - - 60 + + Event counter + + + + + + + false + + + + 0 + 0 + + + + Uses Valgrind Callgrind when executing benchmarks (it must be installed). + + + Callgrind + + + + + + + false + + + + 0 + 0 + + + + Uses Perf when executing benchmarks (it must be installed). + + + Perf - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 40 - 20 - - - - - - - - - - Hides internal messages by default. You can still enable them by using the test results filter. - - - Omit internal messages - - - true - - - - - - - Hides warnings related to a guessed run configuration. - - - Omit run configuration warnings - - - - - - - Limit result output to 100000 characters. - - - Limit result output - - - true - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - - - - 0 - 0 - - - - Benchmark Metrics - - - - - - - - - 0 - 0 - - - - Uses walltime metrics for executing benchmarks (default). - - - Walltime - - - true - - - - - - - - 0 - 0 - - - - Uses tick counter when executing benchmarks. - - - Tick counter - - - - - - - - 0 - 0 - - - - Uses event counter when executing benchmarks. - - - Event counter - - - - - - - false - - - - 0 - 0 - - - - Uses Valgrind Callgrind when executing benchmarks (it must be installed). - - - Callgrind - - - - - - - false - - - - 0 - 0 - - - - Uses Perf when executing benchmarks (it must be installed). - - - Perf - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + General + + + + + + Hides internal messages by default. You can still enable them by using the test results filter. + + + Omit internal messages + + + true + + + + + + + Hides warnings related to a guessed run configuration. + + + Omit run configuration warnings + + + + + + + Limit result output to 100000 characters. + + + Limit result output + + + true + + + + + + + Automatically scroll down when new items are added and scrollbar is at bottom. + + + Automatically scroll results + + + true + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + From 8260b79458927cff98b4c09f7e0083753effc40d Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 27 Apr 2015 16:11:28 +0200 Subject: [PATCH 111/200] Fix getting test configuration information This was especially wrong if the information is not available before building the project. Now the information will be fetched after a possible automatic build had been done. Change-Id: If92bc714039733700885820648471e355199079d Reviewed-by: David Schulz --- plugins/autotest/testconfiguration.cpp | 117 +++++++++++++++++++++- plugins/autotest/testconfiguration.h | 8 +- plugins/autotest/testrunner.cpp | 32 +++--- plugins/autotest/testtreemodel.cpp | 131 ++++--------------------- 4 files changed, 155 insertions(+), 133 deletions(-) diff --git a/plugins/autotest/testconfiguration.cpp b/plugins/autotest/testconfiguration.cpp index 7c161289ef4..4b294f47820 100644 --- a/plugins/autotest/testconfiguration.cpp +++ b/plugins/autotest/testconfiguration.cpp @@ -19,7 +19,17 @@ #include "testconfiguration.h" +#include + +#include +#include +#include #include +#include +#include +#include + +using namespace ProjectExplorer; namespace Autotest { namespace Internal { @@ -34,9 +44,8 @@ TestConfiguration::TestConfiguration(const QString &testClass, const QStringList m_project(0), m_guessedConfiguration(false) { - if (testCases.size() != 0) { + if (testCases.size() != 0) m_testCaseCount = testCases.size(); - } } TestConfiguration::~TestConfiguration() @@ -44,6 +53,103 @@ TestConfiguration::~TestConfiguration() m_testCases.clear(); } +void basicProjectInformation(Project *project, const QString &mainFilePath, QString *proFile, + QString *displayName, Project **targetProject) +{ + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + QList projParts = cppMM->projectInfo(project).projectParts(); + + foreach (const CppTools::ProjectPart::Ptr &part, projParts) { + foreach (const CppTools::ProjectFile currentFile, part->files) { + if (currentFile.path == mainFilePath) { + *proFile = part->projectFile; + *displayName = part->displayName; + *targetProject = part->project; + return; + } + } + } +} + +void extractEnvironmentInformation(LocalApplicationRunConfiguration *localRunConfiguration, + QString *workDir, Utils::Environment *env) +{ + *workDir = Utils::FileUtils::normalizePathName(localRunConfiguration->workingDirectory()); + if (auto environmentAspect = localRunConfiguration->extraAspect()) + *env = environmentAspect->environment(); +} + +void TestConfiguration::completeTestInformation() +{ + QTC_ASSERT(!m_mainFilePath.isEmpty(), return); + + typedef LocalApplicationRunConfiguration LocalRunConfig; + + Project *project = SessionManager::startupProject(); + if (!project) + return; + + QString targetFile; + QString targetName; + QString workDir; + QString proFile; + QString displayName; + Project *targetProject = 0; + Utils::Environment env; + bool hasDesktopTarget = false; + bool guessedRunConfiguration = false; + setProject(0); + + basicProjectInformation(project, m_mainFilePath, &proFile, &displayName, &targetProject); + + Target *target = project->activeTarget(); + if (!target) + return; + + BuildTargetInfoList appTargets = target->applicationTargets(); + foreach (const BuildTargetInfo &bti, appTargets.list) { + // some project manager store line/column information as well inside ProjectPart + if (bti.isValid() && proFile.startsWith(bti.projectFilePath.toString())) { + targetFile = Utils::HostOsInfo::withExecutableSuffix(bti.targetFilePath.toString()); + targetName = bti.targetName; + break; + } + } + + QList rcs = target->runConfigurations(); + foreach (RunConfiguration *rc, rcs) { + auto config = qobject_cast(rc); + if (config && config->executable() == targetFile) { + extractEnvironmentInformation(config, &workDir, &env); + hasDesktopTarget = true; + break; + } + } + + // if we could not figure out the run configuration + // try to use the run configuration of the parent project + if (!hasDesktopTarget && targetProject && !targetFile.isEmpty()) { + if (auto config = qobject_cast(target->activeRunConfiguration())) { + extractEnvironmentInformation(config, &workDir, &env); + hasDesktopTarget = true; + guessedRunConfiguration = true; + } + } + + setProFile(proFile); + setDisplayName(displayName); + + if (hasDesktopTarget) { + setTargetFile(targetFile); + setTargetName(targetName); + setWorkingDirectory(workDir); + setEnvironment(env); + setProject(project); + setGuessedConfiguration(guessedRunConfiguration); + } +} + + /** * @brief sets the test cases for this test configuration. * @@ -64,6 +170,11 @@ void TestConfiguration::setTestCaseCount(int count) m_testCaseCount = count; } +void TestConfiguration::setMainFilePath(const QString &mainFile) +{ + m_mainFilePath = mainFile; +} + void TestConfiguration::setTargetFile(const QString &targetFile) { m_targetFile = targetFile; @@ -94,7 +205,7 @@ void TestConfiguration::setEnvironment(const Utils::Environment &env) m_environment = env; } -void TestConfiguration::setProject(ProjectExplorer::Project *project) +void TestConfiguration::setProject(Project *project) { m_project = project; } diff --git a/plugins/autotest/testconfiguration.h b/plugins/autotest/testconfiguration.h index aff75d64058..e1d3bc000e6 100644 --- a/plugins/autotest/testconfiguration.h +++ b/plugins/autotest/testconfiguration.h @@ -41,8 +41,11 @@ public: int testCaseCount = 0, QObject *parent = 0); ~TestConfiguration(); + void completeTestInformation(); + void setTestCases(const QStringList &testCases); void setTestCaseCount(int count); + void setMainFilePath(const QString &mainFile); void setTargetFile(const QString &targetFile); void setTargetName(const QString &targetName); void setProFile(const QString &proFile); @@ -66,14 +69,11 @@ public: bool unnamedOnly() const { return m_unnamedOnly; } bool guessedConfiguration() const { return m_guessedConfiguration; } -signals: - -public slots: - private: QString m_testClass; QStringList m_testCases; int m_testCaseCount; + QString m_mainFilePath; bool m_unnamedOnly; QString m_proFile; QString m_targetFile; diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 07f90a56ad1..bc246ed6aac 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -110,8 +110,16 @@ void performTestRun(QFutureInterface &futureInterface, const QString metricsOption, TestRunner* testRunner) { int testCaseCount = 0; - foreach (const TestConfiguration *config, selectedTests) - testCaseCount += config->testCaseCount(); + foreach (TestConfiguration *config, selectedTests) { + config->completeTestInformation(); + if (config->project()) { + testCaseCount += config->testCaseCount(); + } else { + emitTestResultCreated(FaultyTestResult(Result::MESSAGE_WARN, + QObject::tr("Project is null for \"%1\". Removing from test run.\n" + "Check the test environment.").arg(config->displayName()))); + } + } QProcess testProcess; testProcess.setReadChannelMode(QProcess::MergedChannels); @@ -135,11 +143,16 @@ void performTestRun(QFutureInterface &futureInterface, if (futureInterface.isCanceled()) break; + if (!testConfiguration->project()) + continue; + QProcessEnvironment environment = testConfiguration->environment().toProcessEnvironment(); QString commandFilePath = executableFilePath(testConfiguration->targetFile(), environment); if (commandFilePath.isEmpty()) { emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, - QObject::tr("Could not find command \"%1\".").arg(testConfiguration->targetFile()))); + QObject::tr("Could not find command \"%1\". (%2)") + .arg(testConfiguration->targetFile()) + .arg(testConfiguration->displayName()))); continue; } @@ -197,26 +210,13 @@ void TestRunner::runTests() // clear old log and output pane TestResultsPane::instance()->clearContents(); - // handle faulty test configurations - QList toBeRemoved; foreach (TestConfiguration *config, m_selectedTests) { - if (!config->project()) { - toBeRemoved.append(config); - TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, - tr("Project is null for \"%1\". Removing from test run.\n" - "Check the test environment." - ).arg(config->displayName()))); - } if (displayRunConfigWarnings && config->guessedConfiguration()) { TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, tr("Project's run configuration was guessed for \"%1\".\n" "This might cause trouble during execution.").arg(config->displayName()))); } } - foreach (TestConfiguration *config, toBeRemoved) { - m_selectedTests.removeOne(config); - delete config; - } if (m_selectedTests.empty()) { TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 134a9dc2141..602cea007a7 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -24,21 +24,14 @@ #include -#include -#include -#include #include -#include -#include #include -#include #include #include -#include -#include +#include #include @@ -347,113 +340,22 @@ bool TestTreeModel::hasTests() const return m_autoTestRootItem->childCount() > 0 || m_quickTestRootItem->childCount() > 0; } -static void addProjectInformation(TestConfiguration *config, const QString &filePath) -{ - const ProjectExplorer::SessionManager *session = ProjectExplorer::SessionManager::instance(); - if (!session || !session->hasProjects()) - return; - - ProjectExplorer::Project *project = session->startupProject(); - if (!project) - return; - - QString targetFile; - QString targetName; - QString workDir; - QString proFile; - QString displayName; - ProjectExplorer::Project *targetProject = 0; - Utils::Environment env; - bool hasDesktopTarget = false; - bool guessedRunConfiguration = false; - CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); - QList projParts = cppMM->projectInfo(project).projectParts(); - - if (!projParts.empty()) { - foreach (const CppTools::ProjectPart::Ptr &part, projParts) { - foreach (const CppTools::ProjectFile currentFile, part->files) { - if (currentFile.path == filePath) { - proFile = part->projectFile; - displayName = part->displayName; - targetProject = part->project; - break; - } - } - if (!proFile.isEmpty()) // maybe better use a goto instead of the break above?? - break; - } - } - - if (project) { - if (auto target = project->activeTarget()) { - ProjectExplorer::BuildTargetInfoList appTargets = target->applicationTargets(); - foreach (const ProjectExplorer::BuildTargetInfo &bti, appTargets.list) { - if (bti.isValid() && bti.projectFilePath.toString() == proFile) { - targetFile = Utils::HostOsInfo::withExecutableSuffix(bti.targetFilePath.toString()); - targetName = bti.targetName; - break; - } - } - - QList rcs = target->runConfigurations(); - foreach (ProjectExplorer::RunConfiguration *rc, rcs) { - ProjectExplorer::LocalApplicationRunConfiguration *localRunConfiguration - = qobject_cast(rc); - if (localRunConfiguration && localRunConfiguration->executable() == targetFile) { - hasDesktopTarget = true; - workDir = Utils::FileUtils::normalizePathName( - localRunConfiguration->workingDirectory()); - ProjectExplorer::EnvironmentAspect *envAsp - = localRunConfiguration->extraAspect(); - env = envAsp->environment(); - break; - } - } - - // if we could not figure out the run configuration - // try to use the run configuration of the parent project - if (!hasDesktopTarget && targetProject && !targetFile.isEmpty()) { - auto localRunConfiguration - = qobject_cast(target->activeRunConfiguration()); - if (localRunConfiguration) { - hasDesktopTarget = true; - workDir = Utils::FileUtils::normalizePathName( - localRunConfiguration->workingDirectory()); - ProjectExplorer::EnvironmentAspect *environmentAspect - = localRunConfiguration->extraAspect(); - env = environmentAspect->environment(); - guessedRunConfiguration = true; - } - } - } - } - - if (hasDesktopTarget) { - config->setTargetFile(targetFile); - config->setTargetName(targetName); - config->setWorkingDirectory(workDir); - config->setProFile(proFile); - config->setEnvironment(env); - config->setProject(project); - config->setDisplayName(displayName); - config->setGuessedConfiguration(guessedRunConfiguration); - } else { - config->setProFile(proFile); - config->setDisplayName(displayName); - } -} - QList TestTreeModel::getAllTestCases() const { QList result; + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); + if (!project) + return result; + // get all Auto Tests for (int row = 0, count = m_autoTestRootItem->childCount(); row < count; ++row) { const TestTreeItem *child = m_autoTestRootItem->child(row); TestConfiguration *tc = new TestConfiguration(child->name(), QStringList(), child->childCount()); - addProjectInformation(tc, child->filePath()); + tc->setMainFilePath(child->filePath()); + tc->setProject(project); result << tc; } @@ -481,7 +383,8 @@ QList TestTreeModel::getAllTestCases() const foreach (const QString &mainFile, foundMains.keys()) { TestConfiguration *tc = new TestConfiguration(QString(), QStringList(), foundMains.value(mainFile)); - addProjectInformation(tc, mainFile); + tc->setMainFilePath(mainFile); + tc->setProject(project); result << tc; } @@ -491,6 +394,10 @@ QList TestTreeModel::getAllTestCases() const QList TestTreeModel::getSelectedTests() const { QList result; + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); + if (!project) + return result; + TestConfiguration *testConfiguration = 0; for (int row = 0, count = m_autoTestRootItem->childCount(); row < count; ++row) { @@ -501,7 +408,8 @@ QList TestTreeModel::getSelectedTests() const continue; case Qt::Checked: testConfiguration = new TestConfiguration(child->name(), QStringList(), child->childCount()); - addProjectInformation(testConfiguration, child->filePath()); + testConfiguration->setMainFilePath(child->filePath()); + testConfiguration->setProject(project); result << testConfiguration; continue; case Qt::PartiallyChecked: @@ -516,7 +424,8 @@ QList TestTreeModel::getSelectedTests() const } testConfiguration = new TestConfiguration(childName, testCases); - addProjectInformation(testConfiguration, child->filePath()); + testConfiguration->setMainFilePath(child->filePath()); + testConfiguration->setProject(project); result << testConfiguration; } } @@ -540,7 +449,8 @@ QList TestTreeModel::getSelectedTests() const testConfiguration = new TestConfiguration(QString(), QStringList()); testConfiguration->setTestCaseCount(1); testConfiguration->setUnnamedOnly(true); - addProjectInformation(testConfiguration, mainFile); + testConfiguration->setMainFilePath(mainFile); + testConfiguration->setProject(project); foundMains.insert(mainFile, testConfiguration); } } @@ -581,7 +491,8 @@ QList TestTreeModel::getSelectedTests() const } } else { tc = new TestConfiguration(QString(), testFunctions); - addProjectInformation(tc, child->mainFile()); + tc->setMainFilePath(child->mainFile()); + tc->setProject(project); foundMains.insert(child->mainFile(), tc); } break; From e9b28403273fb2522ecf34164f8f768bbc7c644e Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 16 Apr 2015 14:04:36 +0200 Subject: [PATCH 112/200] Provide 'Run This Test' context menu entry This menu entry will be added only if current selected test (function) is not an unnamed Quick Test. Otherwise it's now possible to execute a particular test case or just a single test function by using the context menu. This avoids the need of (de)selecting inside the model. Change-Id: I857a3ffe72c72a9dbb06e948045cfe2c7843935d Reviewed-by: David Schulz Reviewed-by: Christian Stenger --- plugins/autotest/testnavigationwidget.cpp | 44 +++++++++++++++++++ plugins/autotest/testnavigationwidget.h | 1 + plugins/autotest/testtreemodel.cpp | 51 +++++++++++++++++++++++ plugins/autotest/testtreemodel.h | 4 +- 4 files changed, 99 insertions(+), 1 deletion(-) diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index f9847a57827..da0de8a7619 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -89,7 +89,27 @@ void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event) const bool enabled = !TestRunner::instance()->isTestRunning() && m_model->parser()->state() == TestCodeParser::Idle; const bool hasTests = m_model->hasTests(); + QMenu menu; + QAction *runThisTest = 0; + const QModelIndexList list = m_view->selectionModel()->selectedIndexes(); + if (list.size() == 1) { + const QModelIndex index = list.first(); + QRect rect(m_view->visualRect(index)); + if (rect.contains(event->pos())) { + // do not provide this menu entry for unnamed Quick Tests as it makes no sense + int type = index.data(TypeRole).toInt(); + const QString &unnamed = tr(Constants::UNNAMED_QUICKTESTS); + if ((type == TestTreeItem::TEST_FUNCTION && index.parent().data().toString() != unnamed) + || (type == TestTreeItem::TEST_CLASS && index.data().toString() != unnamed)) { + runThisTest = new QAction(tr("Run This Test"), &menu); + runThisTest->setEnabled(enabled); + connect(runThisTest, &QAction::triggered, + this, &TestNavigationWidget::onRunThisTestTriggered); + } + } + } + QAction *runAll = Core::ActionManager::command(Constants::ACTION_RUN_ALL_ID)->action(); QAction *runSelected = Core::ActionManager::command(Constants::ACTION_RUN_SELECTED_ID)->action(); QAction *selectAll = new QAction(tr("Select All"), &menu); @@ -106,6 +126,10 @@ void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event) deselectAll->setEnabled(enabled && hasTests); rescan->setEnabled(enabled); + if (runThisTest) { + menu.addAction(runThisTest); + menu.addSeparator(); + } menu.addAction(runAll); menu.addAction(runSelected); menu.addSeparator(); @@ -210,6 +234,26 @@ void TestNavigationWidget::initializeFilterMenu() m_filterMenu->addAction(action); } +void TestNavigationWidget::onRunThisTestTriggered() +{ + const QModelIndexList selected = m_view->selectionModel()->selectedIndexes(); + // paranoia + if (selected.isEmpty()) + return; + const QModelIndex sourceIndex = m_sortFilterModel->mapToSource(selected.first()); + if (!sourceIndex.isValid()) + return; + + TestTreeItem *item = static_cast(sourceIndex.internalPointer()); + if (item->type() == TestTreeItem::TEST_CLASS || item->type() == TestTreeItem::TEST_FUNCTION) { + if (TestConfiguration *configuration = m_model->getTestConfiguration(item)) { + TestRunner *runner = TestRunner::instance(); + runner->setSelectedTests( {configuration} ); + runner->runTests(); + } + } +} + TestNavigationWidgetFactory::TestNavigationWidgetFactory() { setDisplayName(tr("Tests")); diff --git a/plugins/autotest/testnavigationwidget.h b/plugins/autotest/testnavigationwidget.h index a4b4c6f0610..ef281308170 100644 --- a/plugins/autotest/testnavigationwidget.h +++ b/plugins/autotest/testnavigationwidget.h @@ -69,6 +69,7 @@ private slots: private: void initializeFilterMenu(); + void onRunThisTestTriggered(); TestTreeModel *m_model; TestTreeSortFilterModel *m_sortFilterModel; diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 602cea007a7..4639cbd1e94 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -255,6 +255,8 @@ QVariant TestTreeModel::data(const QModelIndex &index, int role) const default: return false; } + case TypeRole: + return item->type(); } // TODO ? @@ -506,6 +508,55 @@ QList TestTreeModel::getSelectedTests() const return result; } +TestConfiguration *TestTreeModel::getTestConfiguration(const TestTreeItem *item) const +{ + QTC_ASSERT(item != 0, return 0); + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); + QTC_ASSERT(project, return 0); + + TestConfiguration *config = 0; + switch (item->type()) { + case TestTreeItem::TEST_CLASS: { + if (item->parent() == m_quickTestRootItem) { + // Quick Test TestCase + QStringList testFunctions; + for (int row = 0, count = item->childCount(); row < count; ++row) { + testFunctions << item->name() + QLatin1String("::") + item->child(row)->name(); + } + config = new TestConfiguration(QString(), testFunctions); + config->setMainFilePath(item->mainFile()); + config->setProject(project); + } else { + // normal auto test + config = new TestConfiguration(item->name(), QStringList(), item->childCount()); + config->setMainFilePath(item->filePath()); + config->setProject(project); + } + break; + } + case TestTreeItem::TEST_FUNCTION: { + const TestTreeItem *parent = item->parent(); + if (parent->parent() == m_quickTestRootItem) { + // it's a Quick Test function of a named TestCase + QStringList testFunction(parent->name() + QLatin1String("::") + item->name()); + config = new TestConfiguration(QString(), testFunction); + config->setMainFilePath(parent->mainFile()); + config->setProject(project); + } else { + // normal auto test + config = new TestConfiguration(parent->name(), QStringList() << item->name()); + config->setMainFilePath(parent->filePath()); + config->setProject(project); + } + break; + } + // not supported items + default: + return 0; + } + return config; +} + QString TestTreeModel::getMainFileForUnnamedQuickTest(const QString &qmlFile) const { const TestTreeItem *unnamed = unnamedQuickTests(); diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 15a00ecb387..785606c36a8 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -31,7 +31,8 @@ namespace { enum ItemRole { // AnnotationRole = Qt::UserRole + 1, LinkRole = Qt::UserRole + 2, // can be removed if AnnotationRole comes back - ItalicRole // used only inside the delegate + ItalicRole, // used only inside the delegate + TypeRole }; } @@ -71,6 +72,7 @@ public: bool hasTests() const; QList getAllTestCases() const; QList getSelectedTests() const; + TestConfiguration *getTestConfiguration(const TestTreeItem *item) const; QString getMainFileForUnnamedQuickTest(const QString &qmlFile) const; void qmlFilesForMainFile(const QString &mainFile, QSet *filePaths) const; QList getUnnamedQuickTestFunctions() const; From a133256e3704a7ca685d2f8082c69e5bc8bdaee9 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 23 Jun 2015 12:51:15 +0200 Subject: [PATCH 113/200] Fix display of benchmark results The '-' could have been misinterpreted as sign of the value following it. Change-Id: Ia308cca93f81e7fa026485e9cda3fcc433696a35 Reviewed-by: David Schulz --- plugins/autotest/testresultdelegate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp index c20ce112007..5e37c64955b 100644 --- a/plugins/autotest/testresultdelegate.cpp +++ b/plugins/autotest/testresultdelegate.cpp @@ -114,7 +114,7 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); if (!desc.isEmpty()) { int breakPos = desc.indexOf(QLatin1Char('(')); - output.append(QLatin1String(" - ")).append(desc.left(breakPos)); + output.append(QLatin1String(": ")).append(desc.left(breakPos)); if (selected) output.append(QLatin1Char('\n')).append(desc.mid(breakPos)); } From eee4f2c6ac87fc42a34be04a755167bb9fdc50d2 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 11 Jun 2015 17:21:54 +0200 Subject: [PATCH 114/200] Make licensechecker dependency optional Change-Id: Ia353ef7065dbd7dd3ff1f3a9293613cf7f14ce37 Reviewed-by: Eike Ziller --- plugins/autotest/autotest.pro | 1 + plugins/autotest/autotest_dependencies.pri | 5 +++-- plugins/autotest/autotestplugin.cpp | 6 +++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/plugins/autotest/autotest.pro b/plugins/autotest/autotest.pro index 4d3c6643f29..4022cb43990 100644 --- a/plugins/autotest/autotest.pro +++ b/plugins/autotest/autotest.pro @@ -7,6 +7,7 @@ include(../../qtcreatorplugin.pri) include(autotest_dependencies.pri) DEFINES += AUTOTEST_LIBRARY +CONFIG(licensechecker): DEFINES += LICENSECHECKER SOURCES += \ testtreeview.cpp \ diff --git a/plugins/autotest/autotest_dependencies.pri b/plugins/autotest/autotest_dependencies.pri index a21b5fce963..74dc51e15b3 100644 --- a/plugins/autotest/autotest_dependencies.pri +++ b/plugins/autotest/autotest_dependencies.pri @@ -5,8 +5,9 @@ QTC_PLUGIN_DEPENDS += \ projectexplorer \ cpptools \ qmljstools \ - qmakeprojectmanager \ - licensechecker + qmakeprojectmanager + +CONFIG(licensechecker): QTC_PLUGIN_DEPENDS += licensechecker QTC_LIB_DEPENDS += \ cplusplus \ diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index a2ab7834187..525f21ae3e1 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -38,7 +38,9 @@ #include -#include +#ifdef LICENSECHECKER +# include +#endif #include #include @@ -89,6 +91,7 @@ QSharedPointer AutotestPlugin::settings() const bool AutotestPlugin::checkLicense() { +#ifdef LICENSECHECKER LicenseChecker::LicenseCheckerPlugin *licenseChecker = ExtensionSystem::PluginManager::getObject(); @@ -97,6 +100,7 @@ bool AutotestPlugin::checkLicense() return false; } else if (!licenseChecker->enterpriseFeatures()) return false; +#endif // LICENSECHECKER return true; } From c7a8a941618a5eb1bfc99c416c5adaa181b472f6 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 24 Jun 2015 15:56:24 +0200 Subject: [PATCH 115/200] qbs build: Soft dependency on LicenseChecker. Change-Id: Ibb1f4ee5996306fe24df72b0cf16d5652a76bc57 Reviewed-by: Christian Stenger --- plugins/autotest/autotest.qbs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/autotest/autotest.qbs b/plugins/autotest/autotest.qbs index 93505bce3ba..4a9ec9e4c81 100644 --- a/plugins/autotest/autotest.qbs +++ b/plugins/autotest/autotest.qbs @@ -1,12 +1,11 @@ import qbs -QtcPlugin { +QtcCommercialPlugin { name: "AutoTest" Depends { name: "Core" } Depends { name: "CppTools" } Depends { name: "CPlusPlus" } - Depends { name: "LicenseChecker" } Depends { name: "ProjectExplorer" } Depends { name: "QmakeProjectManager" } Depends { name: "QmlJS" } From 08ab1b6d76c604960d0dbe9da85b2308508cf012 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 29 Jun 2015 09:22:58 +0200 Subject: [PATCH 116/200] Don't use qApp->processEvents() if not necessary Change-Id: I2e92341530f3d79f9c0b47f2007750582db9a361 Reviewed-by: David Schulz --- plugins/autotest/autotestplugin.cpp | 4 +- plugins/autotest/testnavigationwidget.cpp | 2 +- plugins/autotest/testresultspane.cpp | 4 +- plugins/autotest/testrunner.cpp | 60 +++++++++++------------ plugins/autotest/testrunner.h | 7 +-- 5 files changed, 37 insertions(+), 40 deletions(-) diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index 525f21ae3e1..9c32e0b75c2 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -168,7 +168,7 @@ void AutotestPlugin::onRunAllTriggered() TestRunner *runner = TestRunner::instance(); TestTreeModel *model = TestTreeModel::instance(); runner->setSelectedTests(model->getAllTestCases()); - runner->runTests(); + runner->prepareToRunTests(); } void AutotestPlugin::onRunSelectedTriggered() @@ -176,7 +176,7 @@ void AutotestPlugin::onRunSelectedTriggered() TestRunner *runner = TestRunner::instance(); TestTreeModel *model = TestTreeModel::instance(); runner->setSelectedTests(model->getSelectedTests()); - runner->runTests(); + runner->prepareToRunTests(); } void AutotestPlugin::updateMenuItemsEnabledState() diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index da0de8a7619..9745e1a19b3 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -249,7 +249,7 @@ void TestNavigationWidget::onRunThisTestTriggered() if (TestConfiguration *configuration = m_model->getTestConfiguration(item)) { TestRunner *runner = TestRunner::instance(); runner->setSelectedTests( {configuration} ); - runner->runTests(); + runner->prepareToRunTests(); } } } diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 9ebb1c09fbb..db78e24cd60 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -288,14 +288,14 @@ void TestResultsPane::onRunAllTriggered() { TestRunner *runner = TestRunner::instance(); runner->setSelectedTests(TestTreeModel::instance()->getAllTestCases()); - runner->runTests(); + runner->prepareToRunTests(); } void TestResultsPane::onRunSelectedTriggered() { TestRunner *runner = TestRunner::instance(); runner->setSelectedTests(TestTreeModel::instance()->getSelectedTests()); - runner->runTests(); + runner->prepareToRunTests(); } void TestResultsPane::initializeFilterMenu() diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index bc246ed6aac..b556989d625 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -86,7 +86,6 @@ TestRunner *TestRunner::instance() TestRunner::TestRunner(QObject *parent) : QObject(parent), - m_building(false), m_executingTests(false) { } @@ -197,12 +196,9 @@ void performTestRun(QFutureInterface &futureInterface, futureInterface.setProgressValue(testCaseCount); } -void TestRunner::runTests() +void TestRunner::prepareToRunTests() { - const QSharedPointer settings = AutotestPlugin::instance()->settings(); - const int timeout = settings->timeout; - const QString metricsOption = TestSettings::metricsTypeToOption(settings->metrics); - const bool displayRunConfigWarnings = !settings->omitRunConfigWarn; + const bool omitRunConfigWarnings = AutotestPlugin::instance()->settings()->omitRunConfigWarn; m_executingTests = true; emit testRunStarted(); @@ -211,7 +207,7 @@ void TestRunner::runTests() TestResultsPane::instance()->clearContents(); foreach (TestConfiguration *config, m_selectedTests) { - if (displayRunConfigWarnings && config->guessedConfiguration()) { + if (!omitRunConfigWarnings && config->guessedConfiguration()) { TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, tr("Project's run configuration was guessed for \"%1\".\n" "This might cause trouble during execution.").arg(config->displayName()))); @@ -237,38 +233,31 @@ void TestRunner::runTests() ProjectExplorer::Internal::ProjectExplorerSettings projectExplorerSettings = ProjectExplorer::ProjectExplorerPlugin::projectExplorerSettings(); - if (projectExplorerSettings.buildBeforeDeploy) { - if (!project->hasActiveBuildSettings()) { + if (!projectExplorerSettings.buildBeforeDeploy) { + runTests(); + } else { + if (project->hasActiveBuildSettings()) { + buildProject(project); + } else { TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_FATAL, tr("Project is not configured. Canceling test run."))); onFinished(); return; } - - auto connection = connect(this, &TestRunner::requestStopTestRun, [&] () { - ProjectExplorer::BuildManager::instance()->cancel(); - m_building = false; - m_buildSucceeded = false; - }); - buildProject(project); - while (m_building) { - qApp->processEvents(); - } - disconnect(connection); - - if (!m_buildSucceeded) { - TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_FATAL, - tr("Build failed. Canceling test run."))); - onFinished(); - return; - } } +} + +void TestRunner::runTests() +{ + const QSharedPointer settings = AutotestPlugin::instance()->settings(); + const QString &metricsOption = TestSettings::metricsTypeToOption(settings->metrics); connect(this, &TestRunner::testResultCreated, TestResultsPane::instance(), &TestResultsPane::addTestResult, Qt::QueuedConnection); - QFuture future = QtConcurrent::run(&performTestRun, m_selectedTests, timeout, metricsOption, this); + QFuture future = QtConcurrent::run(&performTestRun, m_selectedTests, settings->timeout, + metricsOption, this); Core::FutureProgress *progress = Core::ProgressManager::addTask(future, tr("Running Tests"), Autotest::Constants::TASK_INDEX); connect(progress, &Core::FutureProgress::finished, @@ -277,9 +266,9 @@ void TestRunner::runTests() void TestRunner::buildProject(ProjectExplorer::Project *project) { - m_building = true; - m_buildSucceeded = false; ProjectExplorer::BuildManager *buildManager = ProjectExplorer::BuildManager::instance(); + m_buildConnect = connect(this, &TestRunner::requestStopTestRun, + buildManager, &ProjectExplorer::BuildManager::cancel); connect(buildManager, &ProjectExplorer::BuildManager::buildQueueFinished, this, &TestRunner::buildFinished); ProjectExplorer::ProjectExplorerPlugin::buildProject(project); @@ -287,11 +276,18 @@ void TestRunner::buildProject(ProjectExplorer::Project *project) void TestRunner::buildFinished(bool success) { + disconnect(m_buildConnect); ProjectExplorer::BuildManager *buildManager = ProjectExplorer::BuildManager::instance(); disconnect(buildManager, &ProjectExplorer::BuildManager::buildQueueFinished, this, &TestRunner::buildFinished); - m_building = false; - m_buildSucceeded = success; + + if (success) { + runTests(); + } else { + TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_FATAL, + tr("Build failed. Canceling test run."))); + onFinished(); + } } void TestRunner::onFinished() diff --git a/plugins/autotest/testrunner.h b/plugins/autotest/testrunner.h index ddbac5e92f7..92de02f67b9 100644 --- a/plugins/autotest/testrunner.h +++ b/plugins/autotest/testrunner.h @@ -51,7 +51,7 @@ signals: void requestStopTestRun(); public slots: - void runTests(); + void prepareToRunTests(); private slots: void buildProject(ProjectExplorer::Project *project); @@ -59,13 +59,14 @@ private slots: void onFinished(); private: + void runTests(); explicit TestRunner(QObject *parent = 0); QList m_selectedTests; - bool m_building; - bool m_buildSucceeded; bool m_executingTests; + // temporarily used if building before running is necessary + QMetaObject::Connection m_buildConnect; }; } // namespace Internal From 400f87fa589da1fcd311e04a94d812757d48fb66 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 13 Jul 2015 10:13:35 +0200 Subject: [PATCH 117/200] Fix deployment of wizards on OSX Task-number: QTCREATORBUG-14490 Change-Id: I41d214f96ce60b2e268585b1b740f47915b0d3df Reviewed-by: Oswald Buddenhagen --- shared/shared.pro | 12 +++++++----- shared/{ => templates/wizards}/autotest/auto.pro | 0 .../wizards}/autotest/autotest_24.png | Bin shared/{ => templates/wizards}/autotest/main.cpp | 0 shared/{ => templates/wizards}/autotest/src.pro | 0 shared/{ => templates/wizards}/autotest/tests.pro | 0 shared/{ => templates/wizards}/autotest/tmp.pro | 0 shared/{ => templates/wizards}/autotest/tst.pro | 0 shared/{ => templates/wizards}/autotest/tst_src.cpp | 0 shared/{ => templates/wizards}/autotest/wizard.xml | 0 10 files changed, 7 insertions(+), 5 deletions(-) rename shared/{ => templates/wizards}/autotest/auto.pro (100%) rename shared/{ => templates/wizards}/autotest/autotest_24.png (100%) rename shared/{ => templates/wizards}/autotest/main.cpp (100%) rename shared/{ => templates/wizards}/autotest/src.pro (100%) rename shared/{ => templates/wizards}/autotest/tests.pro (100%) rename shared/{ => templates/wizards}/autotest/tmp.pro (100%) rename shared/{ => templates/wizards}/autotest/tst.pro (100%) rename shared/{ => templates/wizards}/autotest/tst_src.cpp (100%) rename shared/{ => templates/wizards}/autotest/wizard.xml (100%) diff --git a/shared/shared.pro b/shared/shared.pro index e74d4d09acd..05c3c34dbf6 100644 --- a/shared/shared.pro +++ b/shared/shared.pro @@ -1,10 +1,12 @@ TEMPLATE = aux -content.files = \ - autotest +STATIC_BASE = $$PWD +STATIC_DIRS = templates -content.path = $$QTC_PREFIX/share/qtcreator/templates/wizards +for(data_dir, STATIC_DIRS) { + files = $$files($$STATIC_BASE/$$data_dir/*, true) + for(file, files): !exists($$file/*): STATIC_FILES += $$file +} -OTHER_FILES += $${content.files} +include(../../qtcreator/share/qtcreator/static.pri) -INSTALLS += content diff --git a/shared/autotest/auto.pro b/shared/templates/wizards/autotest/auto.pro similarity index 100% rename from shared/autotest/auto.pro rename to shared/templates/wizards/autotest/auto.pro diff --git a/shared/autotest/autotest_24.png b/shared/templates/wizards/autotest/autotest_24.png similarity index 100% rename from shared/autotest/autotest_24.png rename to shared/templates/wizards/autotest/autotest_24.png diff --git a/shared/autotest/main.cpp b/shared/templates/wizards/autotest/main.cpp similarity index 100% rename from shared/autotest/main.cpp rename to shared/templates/wizards/autotest/main.cpp diff --git a/shared/autotest/src.pro b/shared/templates/wizards/autotest/src.pro similarity index 100% rename from shared/autotest/src.pro rename to shared/templates/wizards/autotest/src.pro diff --git a/shared/autotest/tests.pro b/shared/templates/wizards/autotest/tests.pro similarity index 100% rename from shared/autotest/tests.pro rename to shared/templates/wizards/autotest/tests.pro diff --git a/shared/autotest/tmp.pro b/shared/templates/wizards/autotest/tmp.pro similarity index 100% rename from shared/autotest/tmp.pro rename to shared/templates/wizards/autotest/tmp.pro diff --git a/shared/autotest/tst.pro b/shared/templates/wizards/autotest/tst.pro similarity index 100% rename from shared/autotest/tst.pro rename to shared/templates/wizards/autotest/tst.pro diff --git a/shared/autotest/tst_src.cpp b/shared/templates/wizards/autotest/tst_src.cpp similarity index 100% rename from shared/autotest/tst_src.cpp rename to shared/templates/wizards/autotest/tst_src.cpp diff --git a/shared/autotest/wizard.xml b/shared/templates/wizards/autotest/wizard.xml similarity index 100% rename from shared/autotest/wizard.xml rename to shared/templates/wizards/autotest/wizard.xml From 3d45123824865b339711ec16150c5cff5c31fae7 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 22 Jul 2015 15:52:01 +0200 Subject: [PATCH 118/200] Fix deployment of wizards on OSX when using build scripts Change-Id: I9e1c223173c0a4e0f77d2c7642cf2d81010c1ff1 Reviewed-by: Kai Koehne --- shared/shared.pro | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shared/shared.pro b/shared/shared.pro index 05c3c34dbf6..306eacb4c5c 100644 --- a/shared/shared.pro +++ b/shared/shared.pro @@ -1,3 +1,6 @@ +isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE=$$(QTC_SOURCE) +isEmpty(IDE_SOURCE_TREE): error(Set QTC_SOURCE environment variable) + TEMPLATE = aux STATIC_BASE = $$PWD @@ -8,5 +11,5 @@ for(data_dir, STATIC_DIRS) { for(file, files): !exists($$file/*): STATIC_FILES += $$file } -include(../../qtcreator/share/qtcreator/static.pri) +include($$IDE_SOURCE_TREE/share/qtcreator/static.pri) From 1108556f1ed423913d927eb501ce6a91d833e169 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 23 Jul 2015 09:14:30 +0200 Subject: [PATCH 119/200] Fix deployment when using build scripts again Change-Id: If4180b1f79c51bdf38ac99e5eb9acebb3b3342bc Reviewed-by: Kai Koehne --- shared/shared.pro | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/shared/shared.pro b/shared/shared.pro index 306eacb4c5c..541044da119 100644 --- a/shared/shared.pro +++ b/shared/shared.pro @@ -1,5 +1,7 @@ -isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE=$$(QTC_SOURCE) -isEmpty(IDE_SOURCE_TREE): error(Set QTC_SOURCE environment variable) +isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE = $$(QTC_SOURCE) +isEmpty(IDE_BUILD_TREE): IDE_BUILD_TREE = $$(QTC_BUILD) +isEmpty(IDE_SOURCE_TREE): error("Set QTC_SOURCE environment variable") +isEmpty(IDE_BUILD_TREE): error("Set QTC_BUILD environment variable") TEMPLATE = aux From 8fd27bc3cfa3a8a73df8ef007362b54fa0af9d37 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 23 Jul 2015 12:53:50 +0200 Subject: [PATCH 120/200] Remove useless currentProject() function Change-Id: I63598256b27a310231935104e6f7beb5ffe0eed7 Reviewed-by: Niels Weber --- plugins/autotest/testcodeparser.cpp | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 004f733fbda..f945e896861 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -76,14 +76,6 @@ TestCodeParser::~TestCodeParser() clearCache(); } -ProjectExplorer::Project *currentProject() -{ - const ProjectExplorer::SessionManager *session = ProjectExplorer::SessionManager::instance(); - if (!session || !session->hasProjects()) - return 0; - return session->startupProject(); -} - void TestCodeParser::setState(State state) { // avoid triggering parse before code model parsing has finished @@ -98,7 +90,8 @@ void TestCodeParser::setState(State state) if (m_parserState == Disabled) { m_fullUpdatePostponed = m_partialUpdatePostponed = false; m_postponedFiles.clear(); - } else if (m_parserState == Idle && m_dirty && currentProject()) { + } else if (m_parserState == Idle && m_dirty + && ProjectExplorer::SessionManager::startupProject()) { scanForTests(m_postponedFiles.toList()); } } @@ -115,7 +108,7 @@ void TestCodeParser::updateTestTree() return; } - if (ProjectExplorer::Project *project = currentProject()) { + if (ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject()) { if (auto qmakeProject = qobject_cast(project)) { if (qmakeProject->asyncUpdateState() != QmakeProjectManager::QmakeProject::Base) { m_fullUpdatePostponed = true; @@ -490,7 +483,7 @@ void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &docume return; } - ProjectExplorer::Project *project = currentProject(); + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); if (!project) return; const QString fileName = document->fileName(); @@ -515,7 +508,7 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) return; } - ProjectExplorer::Project *project = currentProject(); + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); if (!project) return; const QString fileName = document->fileName(); @@ -545,7 +538,7 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) void TestCodeParser::onProjectPartsUpdated(ProjectExplorer::Project *project) { - if (project != currentProject()) + if (project != ProjectExplorer::SessionManager::startupProject()) return; if (!m_parserEnabled || m_parserState == Disabled) m_fullUpdatePostponed = true; @@ -628,7 +621,7 @@ void TestCodeParser::scanForTests(const QStringList &fileList) bool isSmallChange = !isFullParse && fileList.size() < 6; QStringList list; if (isFullParse) { - list = currentProject()->files(ProjectExplorer::Project::AllFiles); + list = ProjectExplorer::SessionManager::startupProject()->files(ProjectExplorer::Project::AllFiles); if (list.isEmpty()) return; m_parserState = FullParse; @@ -896,7 +889,7 @@ void TestCodeParser::removeUnnamedQuickTestsByName(const QString &fileName) void TestCodeParser::onProFileEvaluated() { - ProjectExplorer::Project *project = currentProject(); + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); if (!project) return; From 9e8df7d2b3e84b5fd51f3a873733cc0232c0840d Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 23 Jul 2015 15:51:38 +0200 Subject: [PATCH 121/200] Rename member to better reflect its meaning Change-Id: I50a1f0ff69f638fceae4887c64be52f7d5b92822 Reviewed-by: Niels Weber --- plugins/autotest/testcodeparser.cpp | 19 +++++++++---------- plugins/autotest/testcodeparser.h | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index f945e896861..edf5102419a 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -55,7 +55,7 @@ namespace Internal { TestCodeParser::TestCodeParser(TestTreeModel *parent) : QObject(parent), m_model(parent), - m_parserEnabled(true), + m_codeModelParsing(false), m_fullUpdatePostponed(false), m_partialUpdatePostponed(false), m_dirty(true), @@ -79,7 +79,7 @@ TestCodeParser::~TestCodeParser() void TestCodeParser::setState(State state) { // avoid triggering parse before code model parsing has finished - if (!m_parserEnabled) + if (m_codeModelParsing) return; if ((state == Disabled || state == Idle) @@ -103,7 +103,7 @@ void TestCodeParser::emitUpdateTestTree() void TestCodeParser::updateTestTree() { - if (!m_parserEnabled) { + if (m_codeModelParsing) { m_fullUpdatePostponed = true; return; } @@ -475,7 +475,7 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr document) void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document) { - if (!m_parserEnabled) { + if (m_codeModelParsing) { if (!m_fullUpdatePostponed) { m_partialUpdatePostponed = true; m_postponedFiles.insert(document->fileName()); @@ -500,7 +500,7 @@ void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &docume void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) { - if (!m_parserEnabled) { + if (m_codeModelParsing) { if (!m_fullUpdatePostponed) { m_partialUpdatePostponed = true; m_postponedFiles.insert(document->fileName()); @@ -540,7 +540,7 @@ void TestCodeParser::onProjectPartsUpdated(ProjectExplorer::Project *project) { if (project != ProjectExplorer::SessionManager::startupProject()) return; - if (!m_parserEnabled || m_parserState == Disabled) + if (m_codeModelParsing || m_parserState == Disabled) m_fullUpdatePostponed = true; else emitUpdateTestTree(); @@ -727,9 +727,8 @@ void TestCodeParser::removeTestsIfNecessaryByProFile(const QString &proFile) void TestCodeParser::onTaskStarted(Core::Id type) { - if (type != CppTools::Constants::TASK_INDEX) - return; - m_parserEnabled = false; + if (type == CppTools::Constants::TASK_INDEX) + m_codeModelParsing = true; } void TestCodeParser::onAllTasksFinished(Core::Id type) @@ -737,7 +736,7 @@ void TestCodeParser::onAllTasksFinished(Core::Id type) // only CPP parsing is relevant as we trigger Qml parsing internally anyway if (type != CppTools::Constants::TASK_INDEX) return; - m_parserEnabled = true; + m_codeModelParsing = false; // avoid illegal parser state if respective widgets became hidden while parsing setState(Idle); diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 1b8215fe507..5a1ad98be4a 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -111,7 +111,7 @@ private: QMap m_cppDocMap; QMap m_quickDocMap; QList m_unnamedQuickDocList; - bool m_parserEnabled; + bool m_codeModelParsing; bool m_fullUpdatePostponed; bool m_partialUpdatePostponed; bool m_dirty; From 8f738836ea0d368f44fa575adf64284cff1aee9b Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 24 Jul 2015 13:48:30 +0200 Subject: [PATCH 122/200] Move signal emission to where it belongs Change-Id: I85dc5793887e3a26bc86fc6615aa3167054ae58a Reviewed-by: Niels Weber --- plugins/autotest/testcodeparser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index edf5102419a..a437bd4d158 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -123,7 +123,6 @@ void TestCodeParser::updateTestTree() m_fullUpdatePostponed = false; clearCache(); - emit cacheCleared(); scanForTests(); } @@ -659,6 +658,7 @@ void TestCodeParser::clearCache() m_cppDocMap.clear(); m_quickDocMap.clear(); m_unnamedQuickDocList.clear(); + emit cacheCleared(); } void TestCodeParser::removeTestsIfNecessary(const QString &fileName) From 8b4bdb6a0023806cf869ec344d75854cd7a848ce Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 27 Jul 2015 10:49:40 +0200 Subject: [PATCH 123/200] Consolidate duplicate code Change-Id: I0cae5df1b1f5a8ddab063dc37e1dcd0cb97701a0 Reviewed-by: Niels Weber --- plugins/autotest/testcodeparser.cpp | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index a437bd4d158..0cf2ba56755 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -557,7 +557,8 @@ bool TestCodeParser::postponed(const QStringList &fileList) case Idle: return false; case PartialParse: - // partial is running, postponing a full parse + case FullParse: + // parse is running, postponing a full parse if (fileList.isEmpty()) { m_partialUpdatePostponed = false; m_postponedFiles.clear(); @@ -567,23 +568,6 @@ bool TestCodeParser::postponed(const QStringList &fileList) if (m_fullUpdatePostponed) return true; // partial parse triggered, postpone or add current files to already postponed partial - foreach (const QString &file, fileList) - m_postponedFiles.insert(file); - m_partialUpdatePostponed = true; - } - return true; - case FullParse: - // full parse is running, postponing another full parse - if (fileList.isEmpty()) { - m_partialUpdatePostponed = false; - m_postponedFiles.clear(); - m_fullUpdatePostponed = true; - } else { - // full parse already postponed, ignoring triggering a partial parse - if (m_fullUpdatePostponed) { - return true; - } - // partial parse triggered, postpone or add current files to already postponed partial foreach (const QString &file, fileList) m_postponedFiles.insert(file); m_partialUpdatePostponed = true; From 4fbc020ddc8d353aba8c2c3c79223eaf09be573e Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 27 Jul 2015 10:44:14 +0200 Subject: [PATCH 124/200] Ensure we do not interfere with ourselves while parsing Change-Id: I4e22e91273737321e7dbfa10e50b4ae1f4ee63f9 Reviewed-by: Niels Weber --- plugins/autotest/testcodeparser.cpp | 49 +++++++++++++++++++---------- plugins/autotest/testcodeparser.h | 2 ++ plugins/autotest/testtreemodel.cpp | 2 +- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 0cf2ba56755..982bffbffcb 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -59,6 +59,7 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent) m_fullUpdatePostponed(false), m_partialUpdatePostponed(false), m_dirty(true), + m_waitForParseTaskFinish(false), m_parserState(Disabled) { // connect to ProgressManager to postpone test parsing when CppModelManager is parsing @@ -78,9 +79,11 @@ TestCodeParser::~TestCodeParser() void TestCodeParser::setState(State state) { - // avoid triggering parse before code model parsing has finished - if (m_codeModelParsing) + // avoid triggering parse before code model parsing has finished, but mark as dirty + if (m_codeModelParsing) { + m_dirty = true; return; + } if ((state == Disabled || state == Idle) && (m_parserState == PartialParse || m_parserState == FullParse)) @@ -90,9 +93,13 @@ void TestCodeParser::setState(State state) if (m_parserState == Disabled) { m_fullUpdatePostponed = m_partialUpdatePostponed = false; m_postponedFiles.clear(); - } else if (m_parserState == Idle && m_dirty - && ProjectExplorer::SessionManager::startupProject()) { - scanForTests(m_postponedFiles.toList()); + } else if (m_parserState == Idle && ProjectExplorer::SessionManager::startupProject()) { + if (m_fullUpdatePostponed || m_dirty) { + emitUpdateTestTree(); + } else if (m_partialUpdatePostponed) { + m_partialUpdatePostponed = false; + scanForTests(m_postponedFiles.toList()); + } } } @@ -535,6 +542,17 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) } } +void TestCodeParser::onStartupProjectChanged(ProjectExplorer::Project *) +{ + if (m_parserState == FullParse || m_parserState == PartialParse) { + m_waitForParseTaskFinish = true; + Core::ProgressManager::instance()->cancelTasks(Constants::TASK_PARSE); + } else { + clearCache(); + emitUpdateTestTree(); + } +} + void TestCodeParser::onProjectPartsUpdated(ProjectExplorer::Project *project) { if (project != ProjectExplorer::SessionManager::startupProject()) @@ -713,6 +731,8 @@ void TestCodeParser::onTaskStarted(Core::Id type) { if (type == CppTools::Constants::TASK_INDEX) m_codeModelParsing = true; + else if (type == Constants::TASK_PARSE) + m_waitForParseTaskFinish = true; } void TestCodeParser::onAllTasksFinished(Core::Id type) @@ -721,19 +741,16 @@ void TestCodeParser::onAllTasksFinished(Core::Id type) if (type != CppTools::Constants::TASK_INDEX) return; m_codeModelParsing = false; + + if (m_waitForParseTaskFinish && type == Constants::TASK_PARSE) { + m_waitForParseTaskFinish = false; + clearCache(); + emitUpdateTestTree(); + return; + } + // avoid illegal parser state if respective widgets became hidden while parsing setState(Idle); - - if (m_fullUpdatePostponed) - updateTestTree(); - else if (m_partialUpdatePostponed) { - m_partialUpdatePostponed = false; - QStringList tmp; - foreach (const QString &file, m_postponedFiles) - tmp << file; - m_postponedFiles.clear(); - scanForTests(tmp); - } } void TestCodeParser::onFinished() diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 5a1ad98be4a..ecf1caeb84a 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -84,6 +84,7 @@ public slots: void onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document); void onQmlDocumentUpdated(const QmlJS::Document::Ptr &document); + void onStartupProjectChanged(ProjectExplorer::Project *); void onProjectPartsUpdated(ProjectExplorer::Project *project); void removeFiles(const QStringList &files); void onProFileEvaluated(); @@ -115,6 +116,7 @@ private: bool m_fullUpdatePostponed; bool m_partialUpdatePostponed; bool m_dirty; + bool m_waitForParseTaskFinish; QSet m_postponedFiles; State m_parserState; }; diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 4639cbd1e94..2ef7c76c63f 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -102,7 +102,7 @@ void TestTreeModel::enableParsing() ProjectExplorer::SessionManager *sm = ProjectExplorer::SessionManager::instance(); connect(sm, &ProjectExplorer::SessionManager::startupProjectChanged, - m_parser, &TestCodeParser::emitUpdateTestTree); + m_parser, &TestCodeParser::onStartupProjectChanged); CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); connect(cppMM, &CppTools::CppModelManager::documentUpdated, From 7c06e4b768f34f6e840541c22b96700e5bc93849 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 27 Jul 2015 13:54:27 +0200 Subject: [PATCH 125/200] Be more generic regarding supported project types This removes the hard dependency on QmakeProjectManager. Furthermore now unneeded code is removed and some parts of the parsing are slightly modified to support other project types than qmake based projects. Change-Id: I1c23056d5a444ddea857e10fdb71264eb6ecc269 Reviewed-by: Christian Kandeler Reviewed-by: Niels Weber --- plugins/autotest/autotest.qbs | 5 +- plugins/autotest/autotest_dependencies.pri | 7 +- plugins/autotest/testcodeparser.cpp | 108 +++++++-------------- plugins/autotest/testcodeparser.h | 5 +- plugins/autotest/testnavigationwidget.cpp | 2 + plugins/autotest/testtreemodel.cpp | 4 + 6 files changed, 53 insertions(+), 78 deletions(-) diff --git a/plugins/autotest/autotest.qbs b/plugins/autotest/autotest.qbs index 4a9ec9e4c81..a75f91da6d0 100644 --- a/plugins/autotest/autotest.qbs +++ b/plugins/autotest/autotest.qbs @@ -7,11 +7,14 @@ QtcCommercialPlugin { Depends { name: "CppTools" } Depends { name: "CPlusPlus" } Depends { name: "ProjectExplorer" } - Depends { name: "QmakeProjectManager" } Depends { name: "QmlJS" } Depends { name: "QmlJSTools" } Depends { name: "Utils" } + pluginTestDepends: [ + "QmakeProjectManager" + ] + Depends { name: "QtSupport" condition: project.testsEnabled diff --git a/plugins/autotest/autotest_dependencies.pri b/plugins/autotest/autotest_dependencies.pri index 74dc51e15b3..fd6653ecf1b 100644 --- a/plugins/autotest/autotest_dependencies.pri +++ b/plugins/autotest/autotest_dependencies.pri @@ -4,8 +4,7 @@ QTC_PLUGIN_DEPENDS += \ coreplugin \ projectexplorer \ cpptools \ - qmljstools \ - qmakeprojectmanager + qmljstools CONFIG(licensechecker): QTC_PLUGIN_DEPENDS += licensechecker @@ -14,4 +13,8 @@ QTC_LIB_DEPENDS += \ qmljs \ utils +QTC_TEST_DEPENDS += \ + qmakeprojectmanager \ + qtsupport + #QTC_PLUGIN_RECOMMENDS += \ diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 982bffbffcb..337643af6e3 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -33,11 +33,9 @@ #include #include +#include #include -#include -#include - #include #include #include @@ -46,8 +44,10 @@ #include #include +#include #include #include +#include namespace Autotest { namespace Internal { @@ -58,8 +58,9 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent) m_codeModelParsing(false), m_fullUpdatePostponed(false), m_partialUpdatePostponed(false), - m_dirty(true), + m_dirty(false), m_waitForParseTaskFinish(false), + m_singleShotScheduled(false), m_parserState(Disabled) { // connect to ProgressManager to postpone test parsing when CppModelManager is parsing @@ -105,26 +106,22 @@ void TestCodeParser::setState(State state) void TestCodeParser::emitUpdateTestTree() { + if (m_singleShotScheduled) + return; + + m_singleShotScheduled = true; QTimer::singleShot(1000, this, SLOT(updateTestTree())); } void TestCodeParser::updateTestTree() { + m_singleShotScheduled = false; if (m_codeModelParsing) { m_fullUpdatePostponed = true; return; } - if (ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject()) { - if (auto qmakeProject = qobject_cast(project)) { - if (qmakeProject->asyncUpdateState() != QmakeProjectManager::QmakeProject::Base) { - m_fullUpdatePostponed = true; - return; - } - connect(qmakeProject, &QmakeProjectManager::QmakeProject::proFilesEvaluated, - this, &TestCodeParser::onProFileEvaluated, Qt::UniqueConnection); - } - } else + if (!ProjectExplorer::SessionManager::startupProject()) return; m_fullUpdatePostponed = false; @@ -369,6 +366,10 @@ static TestTreeItem constructTestTreeItem(const QString &fileName, /****** end of helpers ******/ +// used internally to indicate a parse that failed due to having triggered a parse for a file that +// is not (yet) part of the CppModelManager's snapshot +static bool parsingHasFailed; + void performParse(QFutureInterface &futureInterface, QStringList list, TestCodeParser *testCodeParser) { @@ -383,6 +384,9 @@ void performParse(QFutureInterface &futureInterface, QStringList list, CPlusPlus::Document::Ptr doc = snapshot.find(file).value(); futureInterface.setProgressValue(++progressValue); testCodeParser->checkDocumentForTestCode(doc); + } else { + parsingHasFailed |= (CppTools::ProjectFile::classify(file) + != CppTools::ProjectFile::Unclassified); } } futureInterface.setProgressValue(list.size()); @@ -618,6 +622,7 @@ void TestCodeParser::scanForTests(const QStringList &fileList) if (postponed(fileList)) return; + m_postponedFiles.clear(); bool isFullParse = fileList.isEmpty(); bool isSmallChange = !isFullParse && fileList.size() < 6; QStringList list; @@ -631,6 +636,7 @@ void TestCodeParser::scanForTests(const QStringList &fileList) m_parserState = PartialParse; } + parsingHasFailed = false; if (isSmallChange) { // no need to do this async or should we do this always async? CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); CPlusPlus::Snapshot snapshot = cppMM->snapshot(); @@ -638,9 +644,12 @@ void TestCodeParser::scanForTests(const QStringList &fileList) if (snapshot.contains(file)) { CPlusPlus::Document::Ptr doc = snapshot.find(file).value(); checkDocumentForTestCode(doc); + } else { + parsingHasFailed |= (CppTools::ProjectFile::classify(file) + != CppTools::ProjectFile::Unclassified); } } - emit onFinished(); + onFinished(); return; } @@ -699,34 +708,6 @@ void TestCodeParser::removeTestsIfNecessary(const QString &fileName) } } -void TestCodeParser::removeTestsIfNecessaryByProFile(const QString &proFile) -{ - QList fList; - foreach (const QString &fileName, m_cppDocMap.keys()) { - if (m_cppDocMap[fileName].proFile() == proFile) - fList.append(fileName); - } - foreach (const QString &fileName, fList) { - m_cppDocMap.remove(fileName); - emit testItemsRemoved(fileName, TestTreeModel::AutoTest); - } - fList.clear(); - foreach (const QString &fileName, m_quickDocMap.keys()) { - if (m_quickDocMap[fileName].proFile() == proFile) - fList.append(fileName); - } - foreach (const QString &fileName, fList) { - m_quickDocMap.remove(fileName); - emit testItemsRemoved(fileName, TestTreeModel::QuickTest); - } - // handle unnamed Quick Tests - const QSet &filePaths = m_model->qmlFilesForProFile(proFile); - foreach (const QString &fileName, filePaths) { - removeUnnamedQuickTestsByName(fileName); - emit unnamedQuickTestsRemoved(fileName); - } -} - void TestCodeParser::onTaskStarted(Core::Id type) { if (type == CppTools::Constants::TASK_INDEX) @@ -762,7 +743,11 @@ void TestCodeParser::onFinished() break; case FullParse: m_parserState = Idle; - emit parsingFinished(); + m_dirty = parsingHasFailed; + if (m_partialUpdatePostponed || m_fullUpdatePostponed || parsingHasFailed) + emit partialParsingFinished(); + else + emit parsingFinished(); m_dirty = false; break; case Disabled: // can happen if all Test related widgets become hidden while parsing @@ -784,14 +769,13 @@ void TestCodeParser::onPartialParsingFinished() updateTestTree(); } else if (m_partialUpdatePostponed) { m_partialUpdatePostponed = false; - QStringList tmp; - foreach (const QString &file, m_postponedFiles) - tmp << file; - m_postponedFiles.clear(); - scanForTests(tmp); + scanForTests(m_postponedFiles.toList()); } else { - m_dirty = false; - emit parsingFinished(); + m_dirty |= m_codeModelParsing; + if (m_dirty) + emit parsingFailed(); + else if (!m_singleShotScheduled) + emit parsingFinished(); } } @@ -887,28 +871,6 @@ void TestCodeParser::removeUnnamedQuickTestsByName(const QString &fileName) } } -void TestCodeParser::onProFileEvaluated() -{ - ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); - if (!project) - return; - - CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); - const QList pp = modelManager->projectInfo(project).projectParts(); - foreach (const CppTools::ProjectPart::Ptr &p, pp) { - if (!p->selectedForBuilding) - removeTestsIfNecessaryByProFile(p->projectFile); - else { - QStringList files; - foreach (auto projectFile, p->files) - files.append(projectFile.path); - // avoid illegal parser state when respective widgets became hidden while evaluating - setState(Idle); - scanForTests(files); - } - } -} - #ifdef WITH_TESTS int TestCodeParser::autoTestsCount() const { diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index ecf1caeb84a..a492990f9b8 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -56,6 +56,7 @@ public: virtual ~TestCodeParser(); void setState(State state); State state() const { return m_parserState; } + void setDirty() { m_dirty = true; } #ifdef WITH_TESTS int autoTestsCount() const; @@ -74,6 +75,7 @@ signals: void unnamedQuickTestsRemoved(const QString &filePath); void parsingStarted(); void parsingFinished(); + void parsingFailed(); void partialParsingFinished(); public slots: @@ -87,14 +89,12 @@ public slots: void onStartupProjectChanged(ProjectExplorer::Project *); void onProjectPartsUpdated(ProjectExplorer::Project *project); void removeFiles(const QStringList &files); - void onProFileEvaluated(); private: bool postponed(const QStringList &fileList); void scanForTests(const QStringList &fileList = QStringList()); void clearCache(); void removeTestsIfNecessary(const QString &fileName); - void removeTestsIfNecessaryByProFile(const QString &proFile); void onTaskStarted(Core::Id type); void onAllTasksFinished(Core::Id type); @@ -117,6 +117,7 @@ private: bool m_partialUpdatePostponed; bool m_dirty; bool m_waitForParseTaskFinish; + bool m_singleShotScheduled; QSet m_postponedFiles; State m_parserState; }; diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index 9745e1a19b3..ad1a496b5f3 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -75,6 +75,8 @@ TestNavigationWidget::TestNavigationWidget(QWidget *parent) : this, &TestNavigationWidget::onParsingStarted); connect(m_model->parser(), &TestCodeParser::parsingFinished, this, &TestNavigationWidget::onParsingFinished); + connect(m_model->parser(), &TestCodeParser::parsingFailed, + this, &TestNavigationWidget::onParsingFinished); connect(m_progressTimer, &QTimer::timeout, m_progressIndicator, &Utils::ProgressIndicator::show); } diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 2ef7c76c63f..5eea7b7d982 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -96,6 +96,10 @@ TestTreeModel::~TestTreeModel() void TestTreeModel::enableParsing() { m_refCounter.ref(); + + if (!m_connectionsInitialized) + m_parser->setDirty(); + m_parser->setState(TestCodeParser::Idle); if (m_connectionsInitialized) return; From 828b61e941fb2247c49c846103f7be5c7c5cbb0a Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 27 Jul 2015 16:07:47 +0200 Subject: [PATCH 126/200] Add qbs project files to unit tests Change-Id: I27918b0beaa39926c13dbf54e1479502a598a598 Reviewed-by: Christian Kandeler --- plugins/autotest/autotest.qbs | 1 + plugins/autotest/autotest_dependencies.pri | 1 + plugins/autotest/autotestunittests.cpp | 60 +++++++++++++++++++ plugins/autotest/autotestunittests.h | 2 + plugins/autotest/autotestunittests.qrc | 11 ++++ .../unit_test/mixed_atp/mixed_atp.qbs | 8 +++ .../autotest/unit_test/mixed_atp/src/src.qbs | 11 ++++ .../unit_test/mixed_atp/tests/auto/auto.qbs | 13 ++++ .../mixed_atp/tests/auto/bench/bench.qbs | 14 +++++ .../mixed_atp/tests/auto/dummy/dummy.qbs | 12 ++++ .../mixed_atp/tests/auto/gui/gui.qbs | 13 ++++ .../tests/auto/quickauto/quickauto.qbs | 33 ++++++++++ .../tests/auto/quickauto2/quickauto2.qbs | 29 +++++++++ .../unit_test/mixed_atp/tests/tests.qbs | 7 +++ plugins/autotest/unit_test/plain/plain.qbs | 7 +++ .../unit_test/plain/test_plain/test_plain.qbs | 10 ++++ 16 files changed, 232 insertions(+) create mode 100644 plugins/autotest/unit_test/mixed_atp/mixed_atp.qbs create mode 100644 plugins/autotest/unit_test/mixed_atp/src/src.qbs create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/auto.qbs create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.qbs create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.qbs create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.qbs create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.qbs create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs create mode 100644 plugins/autotest/unit_test/mixed_atp/tests/tests.qbs create mode 100644 plugins/autotest/unit_test/plain/plain.qbs create mode 100644 plugins/autotest/unit_test/plain/test_plain/test_plain.qbs diff --git a/plugins/autotest/autotest.qbs b/plugins/autotest/autotest.qbs index a75f91da6d0..f746d7fae13 100644 --- a/plugins/autotest/autotest.qbs +++ b/plugins/autotest/autotest.qbs @@ -12,6 +12,7 @@ QtcCommercialPlugin { Depends { name: "Utils" } pluginTestDepends: [ + "QbsProjectManager", "QmakeProjectManager" ] diff --git a/plugins/autotest/autotest_dependencies.pri b/plugins/autotest/autotest_dependencies.pri index fd6653ecf1b..9410d779504 100644 --- a/plugins/autotest/autotest_dependencies.pri +++ b/plugins/autotest/autotest_dependencies.pri @@ -14,6 +14,7 @@ QTC_LIB_DEPENDS += \ utils QTC_TEST_DEPENDS += \ + qbsprojectmanager \ qmakeprojectmanager \ qtsupport diff --git a/plugins/autotest/autotestunittests.cpp b/plugins/autotest/autotestunittests.cpp index 15f32db669c..8878f754183 100644 --- a/plugins/autotest/autotestunittests.cpp +++ b/plugins/autotest/autotestunittests.cpp @@ -117,6 +117,66 @@ void AutoTestUnitTests::testCodeParser_data() QTest::newRow("mixedAutoTestAndQuickTests") << QString(m_tmpDir->path() + QLatin1String("/mixed_atp/mixed_atp.pro")) << 3 << 5 << 3; + QTest::newRow("plainAutoTestQbs") + << QString(m_tmpDir->path() + QLatin1String("/plain/plain.qbs")) + << 1 << 0 << 0; + QTest::newRow("mixedAuotTestAndQuickTestsQbs") + << QString(m_tmpDir->path() + QLatin1String("/mixed_atp/mixed_atp.qbs")) + << 3 << 5 << 3; +} + +void AutoTestUnitTests::testCodeParserSwitchStartup() +{ + QFETCH(QStringList, projectFilePaths); + QFETCH(QList, expectedAutoTestsCount); + QFETCH(QList, expectedNamedQuickTestsCount); + QFETCH(QList, expectedUnnamedQuickTestsCount); + + NavigationWidget *navigation = NavigationWidget::instance(); + navigation->activateSubWidget(Constants::AUTOTEST_ID); + + CppTools::Tests::ProjectOpenerAndCloser projectManager; + for (int i = 0; i < projectFilePaths.size(); ++i) { + qDebug() << "Opening project" << projectFilePaths.at(i); + CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePaths.at(i), true); + QVERIFY(projectInfo.isValid()); + + QSignalSpy parserSpy(m_model->parser(), SIGNAL(parsingFinished())); + QVERIFY(parserSpy.wait(20000)); + + QCOMPARE(m_model->autoTestsCount(), expectedAutoTestsCount.at(i)); + QCOMPARE(m_model->namedQuickTestsCount(), + m_isQt4 ? 0 : expectedNamedQuickTestsCount.at(i)); + QCOMPARE(m_model->unnamedQuickTestsCount(), + m_isQt4 ? 0 : expectedUnnamedQuickTestsCount.at(i)); + + QCOMPARE(m_model->parser()->autoTestsCount(), expectedAutoTestsCount.at(i)); + QCOMPARE(m_model->parser()->namedQuickTestsCount(), + m_isQt4 ? 0 : expectedNamedQuickTestsCount.at(i)); + QCOMPARE(m_model->parser()->unnamedQuickTestsCount(), + m_isQt4 ? 0 : expectedUnnamedQuickTestsCount.at(i)); + } +} + +void AutoTestUnitTests::testCodeParserSwitchStartup_data() +{ + QTest::addColumn("projectFilePaths"); + QTest::addColumn >("expectedAutoTestsCount"); + QTest::addColumn >("expectedNamedQuickTestsCount"); + QTest::addColumn >("expectedUnnamedQuickTestsCount"); + + QStringList projects = QStringList() + << QString(m_tmpDir->path() + QLatin1String("/plain/plain.pro")) + << QString(m_tmpDir->path() + QLatin1String("/mixed_atp/mixed_atp.pro")) + << QString(m_tmpDir->path() + QLatin1String("/plain/plain.qbs")) + << QString(m_tmpDir->path() + QLatin1String("/mixed_atp/mixed_atp.qbs")); + + QList expectedAutoTests = QList() << 1 << 3 << 1 << 3; + QList expectedNamedQuickTests = QList() << 0 << 5 << 0 << 5; + QList expectedUnnamedQuickTests = QList() << 0 << 3 << 0 << 3; + + QTest::newRow("loadMultipleProjects") + << projects << expectedAutoTests << expectedNamedQuickTests << expectedUnnamedQuickTests; } } // namespace Internal diff --git a/plugins/autotest/autotestunittests.h b/plugins/autotest/autotestunittests.h index ab2b7c1b9b4..e359e4175dc 100644 --- a/plugins/autotest/autotestunittests.h +++ b/plugins/autotest/autotestunittests.h @@ -43,6 +43,8 @@ private slots: void cleanupTestCase(); void testCodeParser(); void testCodeParser_data(); + void testCodeParserSwitchStartup(); + void testCodeParserSwitchStartup_data(); private: TestTreeModel *m_model; diff --git a/plugins/autotest/autotestunittests.qrc b/plugins/autotest/autotestunittests.qrc index 6fb5348e544..25ce4044feb 100644 --- a/plugins/autotest/autotestunittests.qrc +++ b/plugins/autotest/autotestunittests.qrc @@ -28,5 +28,16 @@ unit_test/mixed_atp/tests/auto/quickauto/quickauto.pro unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.pro unit_test/mixed_atp/tests/auto/auto.pro + unit_test/plain/plain.qbs + unit_test/plain/test_plain/test_plain.qbs + unit_test/mixed_atp/mixed_atp.qbs + unit_test/mixed_atp/src/src.qbs + unit_test/mixed_atp/tests/tests.qbs + unit_test/mixed_atp/tests/auto/auto.qbs + unit_test/mixed_atp/tests/auto/bench/bench.qbs + unit_test/mixed_atp/tests/auto/dummy/dummy.qbs + unit_test/mixed_atp/tests/auto/gui/gui.qbs + unit_test/mixed_atp/tests/auto/quickauto/quickauto.qbs + unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs
diff --git a/plugins/autotest/unit_test/mixed_atp/mixed_atp.qbs b/plugins/autotest/unit_test/mixed_atp/mixed_atp.qbs new file mode 100644 index 00000000000..dfc99c15df3 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/mixed_atp.qbs @@ -0,0 +1,8 @@ +import qbs + +Project { + references: [ + "src/src.qbs", + "tests/tests.qbs" + ] +} diff --git a/plugins/autotest/unit_test/mixed_atp/src/src.qbs b/plugins/autotest/unit_test/mixed_atp/src/src.qbs new file mode 100644 index 00000000000..5ed4dd4a364 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/src/src.qbs @@ -0,0 +1,11 @@ +import qbs + +CppApplication { + type: "application" + name: "Dummy Application" + + Depends { name: "Qt.gui" } + Depends { name: "Qt.widgets" } + + files: [ "main.cpp" ] +} diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/auto.qbs b/plugins/autotest/unit_test/mixed_atp/tests/auto/auto.qbs new file mode 100644 index 00000000000..a27b3922443 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/auto.qbs @@ -0,0 +1,13 @@ +import qbs + +Project { + name: "Auto tests" + + references: [ + "bench/bench.qbs", + "dummy/dummy.qbs", + "gui/gui.qbs", + "quickauto/quickauto.qbs", + "quickauto2/quickauto2.qbs" + ] +} diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.qbs b/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.qbs new file mode 100644 index 00000000000..d10891316a2 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.qbs @@ -0,0 +1,14 @@ +import qbs + +CppApplication { + type: "application" + name: "Benchmark Auto Test" + targetName: "tst_benchtest" + + Depends { name: "cpp" } + Depends { name: "Qt.test" } + + files: [ "tst_benchtest.cpp" ] + + cpp.defines: base.concat("SRCDIR=" + path) +} diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.qbs b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.qbs new file mode 100644 index 00000000000..012ba11a673 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.qbs @@ -0,0 +1,12 @@ +import qbs + +CppApplication { + type: "application" + name: "Dummy auto test" + targetName: "tst_FooBar" + + Depends { name: "Qt.test" } + Depends { name: "Qt.gui" } + + files: [ "tst_foo.cpp", "tst_foo.h" ] +} diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.qbs b/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.qbs new file mode 100644 index 00000000000..05359cf10fc --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.qbs @@ -0,0 +1,13 @@ +import qbs + +CppApplication { + name: "Gui auto test" + targetName: "tst_gui" + + Depends { name: "Qt"; submodules: [ "gui", "widgets", "test" ] } + Depends { name: "cpp" } + + files: [ "tst_guitest.cpp" ] + + cpp.defines: base.concat("SRCDIR=" + path) +} diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.qbs b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.qbs new file mode 100644 index 00000000000..1697cd51a29 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.qbs @@ -0,0 +1,33 @@ +import qbs + +CppApplication { + name: "Qt Quick auto test" + targetName: "test_mal_qtquick" + + Depends { name: "cpp" } + Depends { name: "Qt.core" } + Depends { + condition: Qt.core.versionMajor > 4 + name: "Qt.qmltest" + } + + Group { + name: "main application" + condition: Qt.core.versionMajor > 4 + + files: [ "main.cpp" ] + } + + Group { + name: "qml test files" + qbs.install: true + + files: [ + "tst_test1.qml", "tst_test2.qml", "TestDummy.qml", + "bar/tst_foo.qml", "tst_test3.qml" + ] + } + + // this should be set automatically, but it seems as if this does not happen + cpp.defines: base.concat("QUICK_TEST_SOURCE_DIR=\"" + path + "\"") +} diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs new file mode 100644 index 00000000000..a5fe65fbd65 --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs @@ -0,0 +1,29 @@ +import qbs + +CppApplication { + name: "Qt Quick auto test 2" + targetName: "test_mal_qtquick" + + Depends { name: "cpp" } + Depends { name: "Qt.core" } + Depends { + condition: Qt.core.versionMajor > 4 + name: "Qt.qmltest" + } + + Group { + condition: Qt.core.versionMajor > 4 + name: "main application" + files: [ "main.cpp" ] + } + + Group { + name: "qml test files" + qbs.install: true + + files: [ "tst_test1.qml", "tst_test2.qml" ] + } + + // this should be set automatically, but it seems as if this does not happen + cpp.defines: base.concat("QUICK_TEST_SOURCE_DIR=\"" + path + "\"") +} diff --git a/plugins/autotest/unit_test/mixed_atp/tests/tests.qbs b/plugins/autotest/unit_test/mixed_atp/tests/tests.qbs new file mode 100644 index 00000000000..e62815789fc --- /dev/null +++ b/plugins/autotest/unit_test/mixed_atp/tests/tests.qbs @@ -0,0 +1,7 @@ +import qbs + +Project { + name: "Tests" + + references: [ "auto/auto.qbs" ] +} diff --git a/plugins/autotest/unit_test/plain/plain.qbs b/plugins/autotest/unit_test/plain/plain.qbs new file mode 100644 index 00000000000..c2fe33618a8 --- /dev/null +++ b/plugins/autotest/unit_test/plain/plain.qbs @@ -0,0 +1,7 @@ +import qbs + +Project { + name: "Plain test project" + + references: [ "test_plain/test_plain.qbs" ] +} diff --git a/plugins/autotest/unit_test/plain/test_plain/test_plain.qbs b/plugins/autotest/unit_test/plain/test_plain/test_plain.qbs new file mode 100644 index 00000000000..1b7937ce6a4 --- /dev/null +++ b/plugins/autotest/unit_test/plain/test_plain/test_plain.qbs @@ -0,0 +1,10 @@ +import qbs + +CppApplication { + type: "application" // suppress bundle generation on OSX + + Depends { name: "Qt.gui" } + Depends { name: "Qt.test" } + + files: [ "tst_simple.cpp", "tst_simple.h" ] +} From 5386fda85145132a37042593a4d48b05f4ea1fdc Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Mon, 10 Aug 2015 14:08:29 +0200 Subject: [PATCH 127/200] Preferences: Options page needs unique ID Task-number: QTCREATORBUG-14742 Change-Id: I81f21ac5ccd4d0d2e5775e7d816bfd91ef927e84 Reviewed-by: Christian Stenger --- plugins/autotest/testsettingspage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/autotest/testsettingspage.cpp b/plugins/autotest/testsettingspage.cpp index cf96ef92b63..643704649ce 100644 --- a/plugins/autotest/testsettingspage.cpp +++ b/plugins/autotest/testsettingspage.cpp @@ -91,7 +91,7 @@ TestSettings TestSettingsWidget::settings() const TestSettingsPage::TestSettingsPage(const QSharedPointer &settings) : m_settings(settings), m_widget(0) { - setId("A.General"); + setId("A.AutoTest.General"); setDisplayName(tr("General")); setCategory(Constants::AUTOTEST_SETTINGS_CATEGORY); setDisplayCategory(tr("Test Settings")); From 565712d84b2c7f108beb98c9f0409a41b626c14f Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 6 Aug 2015 13:58:53 +0200 Subject: [PATCH 128/200] Remove useless code Introduced with 4fbc020ddc8d353aba8c2c3c79223eaf09be573e Change-Id: I28b6b7ea0cfdcc670e83e1114c546d00231a7027 Reviewed-by: Niels Weber --- plugins/autotest/testcodeparser.cpp | 11 ----------- plugins/autotest/testcodeparser.h | 1 - 2 files changed, 12 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 337643af6e3..d0779f67305 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -59,7 +59,6 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent) m_fullUpdatePostponed(false), m_partialUpdatePostponed(false), m_dirty(false), - m_waitForParseTaskFinish(false), m_singleShotScheduled(false), m_parserState(Disabled) { @@ -549,7 +548,6 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) void TestCodeParser::onStartupProjectChanged(ProjectExplorer::Project *) { if (m_parserState == FullParse || m_parserState == PartialParse) { - m_waitForParseTaskFinish = true; Core::ProgressManager::instance()->cancelTasks(Constants::TASK_PARSE); } else { clearCache(); @@ -712,8 +710,6 @@ void TestCodeParser::onTaskStarted(Core::Id type) { if (type == CppTools::Constants::TASK_INDEX) m_codeModelParsing = true; - else if (type == Constants::TASK_PARSE) - m_waitForParseTaskFinish = true; } void TestCodeParser::onAllTasksFinished(Core::Id type) @@ -723,13 +719,6 @@ void TestCodeParser::onAllTasksFinished(Core::Id type) return; m_codeModelParsing = false; - if (m_waitForParseTaskFinish && type == Constants::TASK_PARSE) { - m_waitForParseTaskFinish = false; - clearCache(); - emitUpdateTestTree(); - return; - } - // avoid illegal parser state if respective widgets became hidden while parsing setState(Idle); } diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index a492990f9b8..5bb54d93203 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -116,7 +116,6 @@ private: bool m_fullUpdatePostponed; bool m_partialUpdatePostponed; bool m_dirty; - bool m_waitForParseTaskFinish; bool m_singleShotScheduled; QSet m_postponedFiles; State m_parserState; From d87b4668dc44c6a30b753e69328e71c5a2f57e31 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 4 Aug 2015 09:01:33 +0200 Subject: [PATCH 129/200] Fix postponing when code model is parsed If postponing a full parse unset an already postponed partial parse otherwise we could run into the Q_ASSERT statement inside onPartialParsingFinished(). Change-Id: Iee197f1e16496ea87975d5ead0e43953353ab9a7 Reviewed-by: Niels Weber --- plugins/autotest/testcodeparser.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index d0779f67305..b64c7f6e7d7 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -117,6 +117,8 @@ void TestCodeParser::updateTestTree() m_singleShotScheduled = false; if (m_codeModelParsing) { m_fullUpdatePostponed = true; + m_partialUpdatePostponed = false; + m_postponedFiles.clear(); return; } From 20f050721b80af40f34a611379e7d0f59c098c97 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 28 Jul 2015 14:02:52 +0200 Subject: [PATCH 130/200] Add logging capability to code parser Helps to get more information when something goes wrong. Can be enabled by setting QT_LOGGING_RULES to qtc.autotest.testcodeparser.debug=true Change-Id: Ic168029912f8af509d6a822440658225c7f04eab Reviewed-by: Niels Weber --- plugins/autotest/testcodeparser.cpp | 47 ++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index b64c7f6e7d7..d01fb3140fa 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -47,8 +47,11 @@ #include #include #include +#include #include +static Q_LOGGING_CATEGORY(LOG, "qtc.autotest.testcodeparser") + namespace Autotest { namespace Internal { @@ -79,15 +82,19 @@ TestCodeParser::~TestCodeParser() void TestCodeParser::setState(State state) { + qCDebug(LOG) << "setState(" << state << "), currentState:" << m_parserState; // avoid triggering parse before code model parsing has finished, but mark as dirty if (m_codeModelParsing) { m_dirty = true; + qCDebug(LOG) << "Not setting new state - code model parsing is running, just marking dirty"; return; } if ((state == Disabled || state == Idle) - && (m_parserState == PartialParse || m_parserState == FullParse)) + && (m_parserState == PartialParse || m_parserState == FullParse)) { + qCDebug(LOG) << "Not setting state, parse is running"; return; + } m_parserState = state; if (m_parserState == Disabled) { @@ -98,6 +105,7 @@ void TestCodeParser::setState(State state) emitUpdateTestTree(); } else if (m_partialUpdatePostponed) { m_partialUpdatePostponed = false; + qCDebug(LOG) << "calling scanForTests with postponed files (setState)"; scanForTests(m_postponedFiles.toList()); } } @@ -105,9 +113,12 @@ void TestCodeParser::setState(State state) void TestCodeParser::emitUpdateTestTree() { - if (m_singleShotScheduled) + if (m_singleShotScheduled) { + qCDebug(LOG) << "not scheduling another updateTestTree"; return; + } + qCDebug(LOG) << "adding singleShot"; m_singleShotScheduled = true; QTimer::singleShot(1000, this, SLOT(updateTestTree())); } @@ -128,6 +139,7 @@ void TestCodeParser::updateTestTree() m_fullUpdatePostponed = false; clearCache(); + qCDebug(LOG) << "calling scanForTests (updateTestTree)"; scanForTests(); } @@ -506,6 +518,7 @@ void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &docume } else if (!project->files(ProjectExplorer::Project::AllFiles).contains(fileName)) { return; } + qCDebug(LOG) << "calling scanForTests (onCppDocumentUpdated)"; scanForTests(QStringList(fileName)); } @@ -534,8 +547,11 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) const CPlusPlus::Snapshot snapshot = CppTools::CppModelManager::instance()->snapshot(); if (m_quickDocMap.contains(fileName) && snapshot.contains(m_quickDocMap[fileName].referencingFile())) { - if (!m_quickDocMap[fileName].referencingFile().isEmpty()) + if (!m_quickDocMap[fileName].referencingFile().isEmpty()) { + qCDebug(LOG) << "calling scanForTests with cached referencing files" + << "(onQmlDocumentUpdated)"; scanForTests(QStringList(m_quickDocMap[fileName].referencingFile())); + } } if (m_unnamedQuickDocList.size() == 0) return; @@ -543,6 +559,7 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document) // special case of having unnamed TestCases const QString &mainFile = m_model->getMainFileForUnnamedQuickTest(fileName); if (!mainFile.isEmpty() && snapshot.contains(mainFile)) { + qCDebug(LOG) << "calling scanForTests with mainfile (onQmlDocumentUpdated)"; scanForTests(QStringList(mainFile)); } } @@ -630,9 +647,11 @@ void TestCodeParser::scanForTests(const QStringList &fileList) list = ProjectExplorer::SessionManager::startupProject()->files(ProjectExplorer::Project::AllFiles); if (list.isEmpty()) return; + qCDebug(LOG) << "setting state to FullParse (scanForTests)"; m_parserState = FullParse; } else { list << fileList; + qCDebug(LOG) << "setting state to PartialParse (scanForTests)"; m_parserState = PartialParse; } @@ -729,19 +748,25 @@ void TestCodeParser::onFinished() { switch (m_parserState) { case PartialParse: + qCDebug(LOG) << "setting state to Idle (onFinished, PartialParse)"; m_parserState = Idle; emit partialParsingFinished(); break; case FullParse: + qCDebug(LOG) << "setting state to Idle (onFinished, FullParse)"; m_parserState = Idle; m_dirty = parsingHasFailed; - if (m_partialUpdatePostponed || m_fullUpdatePostponed || parsingHasFailed) + if (m_partialUpdatePostponed || m_fullUpdatePostponed || parsingHasFailed) { emit partialParsingFinished(); - else + } else { + qCDebug(LOG) << "emitting parsingFinished" + << "(onFinished, FullParse, nothing postponed, parsing succeeded)"; emit parsingFinished(); + } m_dirty = false; break; case Disabled: // can happen if all Test related widgets become hidden while parsing + qCDebug(LOG) << "emitting parsingFinished (onFinished, Disabled)"; emit parsingFinished(); break; default: @@ -757,16 +782,24 @@ void TestCodeParser::onPartialParsingFinished() m_partialUpdatePostponed = false;m_postponedFiles.clear();); if (m_fullUpdatePostponed) { m_fullUpdatePostponed = false; + qCDebug(LOG) << "calling updateTestTree (onPartialParsingFinished)"; updateTestTree(); } else if (m_partialUpdatePostponed) { m_partialUpdatePostponed = false; + qCDebug(LOG) << "calling scanForTests with postponed files (onPartialParsingFinished)"; scanForTests(m_postponedFiles.toList()); } else { m_dirty |= m_codeModelParsing; - if (m_dirty) + if (m_dirty) { emit parsingFailed(); - else if (!m_singleShotScheduled) + } else if (!m_singleShotScheduled) { + qCDebug(LOG) << "emitting parsingFinished" + << "(onPartialParsingFinished, nothing postponed, not dirty)"; emit parsingFinished(); + } else { + qCDebug(LOG) << "not emitting parsingFinished" + << "(on PartialParsingFinished, singleshot scheduled)"; + } } } From cc4ecb36a82343b22e4853b6091f2a64a6fd4683 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 19 Aug 2015 09:53:38 +0200 Subject: [PATCH 131/200] Remove unused code Change-Id: If90c6f9f1a33242ef2a33447cf4cff0b706bc0ea Reviewed-by: Niels Weber --- plugins/autotest/testresultdelegate.cpp | 5 ----- plugins/autotest/testresultdelegate.h | 4 ---- 2 files changed, 9 deletions(-) diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp index 5e37c64955b..57dc2de8474 100644 --- a/plugins/autotest/testresultdelegate.cpp +++ b/plugins/autotest/testresultdelegate.cpp @@ -269,11 +269,6 @@ QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo return s; } -void TestResultDelegate::emitSizeHintChanged(const QModelIndex &index) -{ - emit sizeHintChanged(index); -} - void TestResultDelegate::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { emit sizeHintChanged(current); diff --git a/plugins/autotest/testresultdelegate.h b/plugins/autotest/testresultdelegate.h index 8bc5d58ad86..0b837ed2b2b 100644 --- a/plugins/autotest/testresultdelegate.h +++ b/plugins/autotest/testresultdelegate.h @@ -37,10 +37,6 @@ public: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; - void emitSizeHintChanged(const QModelIndex &index); - -signals: - public slots: void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); From 3ee77bd119476fbb83c21c78f80659a709221c99 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 19 Aug 2015 13:35:33 +0200 Subject: [PATCH 132/200] Fix getSelectedTests() for Quick Tests having special functions Quick Tests with special functions (init(), cleanup(),...) must not try to execute these functions explicitly. Change-Id: Ia9a4e9c2788110bb61a70796b0e3a4b9b2091a49 Reviewed-by: Niels Weber Reviewed-by: David Schulz --- plugins/autotest/testtreemodel.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 4639cbd1e94..605167c2493 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -475,6 +475,8 @@ QList TestTreeModel::getSelectedTests() const int grandChildCount = child->childCount(); for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) { const TestTreeItem *grandChild = child->child(grandChildRow); + if (grandChild->type() != TestTreeItem::TEST_FUNCTION) + continue; if (grandChild->checked() == Qt::Checked) testFunctions << child->name() + QLatin1String("::") + grandChild->name(); } From afcb9283b0f7f8a8e9f1c1376b378353f6a6fd9d Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 3 Aug 2015 14:56:18 +0200 Subject: [PATCH 133/200] Store location of definition of functions... ...instead of declarations. Declarations will now be used only as fallback if definition cannot be found for some reason. Change-Id: I1b79622e70d2227cd715f3d82b12f36997080a2e Reviewed-by: Nikolai Kosjar Reviewed-by: Niels Weber --- plugins/autotest/testvisitor.cpp | 16 ++++++++++++---- plugins/autotest/testvisitor.h | 3 +++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/plugins/autotest/testvisitor.cpp b/plugins/autotest/testvisitor.cpp index 2d38cb56b4c..d0179c1ca72 100644 --- a/plugins/autotest/testvisitor.cpp +++ b/plugins/autotest/testvisitor.cpp @@ -68,11 +68,19 @@ bool TestVisitor::visit(CPlusPlus::Class *symbol) if (const auto func = type->asFunctionType()) { if (func->isSlot() && member->isPrivate()) { const QString name = o.prettyName(func->name()); - // TODO use definition of function instead of declaration! TestCodeLocationAndType locationAndType; - locationAndType.m_fileName = QLatin1String(member->fileName()); - locationAndType.m_line = member->line(); - locationAndType.m_column = member->column() - 1; + + CPlusPlus::Function *functionDefinition = m_symbolFinder.findMatchingDefinition( + func, CppTools::CppModelManager::instance()->snapshot(), true); + if (functionDefinition) { + locationAndType.m_fileName = QString::fromUtf8(functionDefinition->fileName()); + locationAndType.m_line = functionDefinition->line(); + locationAndType.m_column = functionDefinition->column() - 1; + } else { // if we cannot find the definition use declaration as fallback + locationAndType.m_fileName = QString::fromUtf8(member->fileName()); + locationAndType.m_line = member->line(); + locationAndType.m_column = member->column() - 1; + } if (specialFunctions.contains(name)) locationAndType.m_type = TestTreeItem::TEST_SPECIALFUNCTION; else if (name.endsWith(QLatin1String("_data"))) diff --git a/plugins/autotest/testvisitor.h b/plugins/autotest/testvisitor.h index 279aca6cbe5..07d58352930 100644 --- a/plugins/autotest/testvisitor.h +++ b/plugins/autotest/testvisitor.h @@ -27,6 +27,8 @@ #include #include +#include + #include #include @@ -47,6 +49,7 @@ public: bool visit(CPlusPlus::Class *symbol); private: + CppTools::SymbolFinder m_symbolFinder; QString m_className; QMap m_privSlots; }; From d284cd99d4143ebe21844347e9a0bc4627494c4c Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 4 Aug 2015 15:53:09 +0200 Subject: [PATCH 134/200] Add basic support for data tags This enables displaying data tags for data functions inside the test tree. Clicking on the data tag opens the editor at the location the respective QTest::newRow() call is done. Change-Id: Ia91bf87437c2608a05bae88ed715711217685fdf Reviewed-by: Nikolai Kosjar --- plugins/autotest/autotest.qrc | 1 + plugins/autotest/images/data.png | Bin 0 -> 646 bytes plugins/autotest/testcodeparser.cpp | 54 ++++++++++- plugins/autotest/testtreeitem.h | 5 +- plugins/autotest/testtreemodel.cpp | 25 ++++- plugins/autotest/testvisitor.cpp | 137 +++++++++++++++++++++++++++- plugins/autotest/testvisitor.h | 27 ++++++ 7 files changed, 234 insertions(+), 15 deletions(-) create mode 100644 plugins/autotest/images/data.png diff --git a/plugins/autotest/autotest.qrc b/plugins/autotest/autotest.qrc index 2770aff5fe2..8c70e3ae3f5 100644 --- a/plugins/autotest/autotest.qrc +++ b/plugins/autotest/autotest.qrc @@ -21,5 +21,6 @@ images/run.png images/runselected.png images/stop.png + images/data.png diff --git a/plugins/autotest/images/data.png b/plugins/autotest/images/data.png new file mode 100644 index 0000000000000000000000000000000000000000..1f510c4042474f3ed76bbcafbc3ece42d12a03cb GIT binary patch literal 646 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!tod_7$pLo9liPTt!$#ayIK z{`Zah=XrMj5%y3JVpL)35)e}LEn-}G$xWn0L_;WbokD4zg1Ce4bRka8Rwf}97J&si zJa0B^u-D$@8kNt<9y;S{~(~nloKQiMe%TkR)o2q%{tvzX` zSn~dt$h|eY>)+W)JYTsv>Lk;GlCz(~XXn(+xx9t{<7e0J4`kQ7%YWEdeUX`O-8FTm zkgVca25O6a-E!1Y3(h@$Hg6sG5|NWTnp>a%@t;NQW1`~M|@H?taUh#Bf0+xF*g zMz6YmtGD>RBfBN &testFunctions) +{ + foreach (const QString &functionName, testFunctions.keys()) { + if (functionName.endsWith(QLatin1String("_data")) && + testFunctions.contains(functionName.left(functionName.size() - 5))) { + return true; + } + } + return false; +} + +static QMap checkForDataTags(const QString &fileName, + const QMap &testFunctions) +{ + if (hasFunctionWithDataTagUsage(testFunctions)) { + const CPlusPlus::Snapshot snapshot = CPlusPlus::CppModelManagerBase::instance()->snapshot(); + const QByteArray fileContent = getFileContent(fileName); + CPlusPlus::Document::Ptr document = snapshot.preprocessedDocument(fileContent, fileName); + document->check(); + CPlusPlus::AST *ast = document->translationUnit()->ast(); + TestDataFunctionVisitor visitor(document); + visitor.accept(ast); + return visitor.dataTags(); + } + return QMap(); +} + + static TestTreeItem constructTestTreeItem(const QString &fileName, const QString &mainFile, // used for Quick Tests only const QString &testCaseName, int line, int column, - const QMap functions) + const QMap functions, + const QMap dataTags = QMap()) { TestTreeItem treeItem(testCaseName, fileName, TestTreeItem::TEST_CLASS); treeItem.setMainFile(mainFile); // used for Quick Tests only @@ -368,10 +397,24 @@ static TestTreeItem constructTestTreeItem(const QString &fileName, foreach (const QString &functionName, functions.keys()) { const TestCodeLocationAndType locationAndType = functions.value(functionName); - TestTreeItem *treeItemChild = new TestTreeItem(functionName, locationAndType.m_fileName, + TestTreeItem *treeItemChild = new TestTreeItem(functionName, locationAndType.m_name, locationAndType.m_type, &treeItem); treeItemChild->setLine(locationAndType.m_line); treeItemChild->setColumn(locationAndType.m_column); + // check for data tags and if there are any for this function add them + const QString qualifiedFunctionName = testCaseName + QLatin1String("::") + functionName; + if (dataTags.contains(qualifiedFunctionName)) { + const TestCodeLocationList &tags = dataTags.value(qualifiedFunctionName); + foreach (const TestCodeLocationAndType &tagLocation, tags) { + TestTreeItem *tagTreeItem = new TestTreeItem(tagLocation.m_name, + locationAndType.m_name, + tagLocation.m_type, treeItemChild); + tagTreeItem->setLine(tagLocation.m_line); + tagTreeItem->setColumn(tagLocation.m_column); + treeItemChild->appendChild(tagTreeItem); + } + } + treeItem.appendChild(treeItemChild); } return treeItem; @@ -437,8 +480,11 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr document) visitor.accept(declaringDoc->globalNamespace()); const QMap testFunctions = visitor.privateSlots(); + const QMap dataTags = + checkForDataTags(declaringDoc->fileName(), testFunctions); TestTreeItem item = constructTestTreeItem(declaringDoc->fileName(), QString(), - testCaseName, line, column, testFunctions); + testCaseName, line, column, testFunctions, + dataTags); updateModelAndCppDocMap(document, declaringDoc->fileName(), item); return; } @@ -487,7 +533,7 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr document) // construct new/modified TestTreeItem TestTreeItem testTreeItem - = constructTestTreeItem(tcLocationAndType.m_fileName, cppFileName, testCaseName, + = constructTestTreeItem(tcLocationAndType.m_name, cppFileName, testCaseName, tcLocationAndType.m_line, tcLocationAndType.m_column, testFunctions); diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index 0cfa1aead11..8c7bf14307f 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -35,6 +35,7 @@ public: ROOT, TEST_CLASS, TEST_FUNCTION, + TEST_DATATAG, TEST_DATAFUNCTION, TEST_SPECIALFUNCTION }; @@ -84,12 +85,14 @@ private: }; struct TestCodeLocationAndType { - QString m_fileName; + QString m_name; // tag name for m_type == TEST_DATATAG, file name for other values unsigned m_line; unsigned m_column; TestTreeItem::Type m_type; }; +typedef QVector TestCodeLocationList; + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 5eea7b7d982..e30b7f651cb 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -180,12 +180,13 @@ int TestTreeModel::columnCount(const QModelIndex &) const static QIcon testTreeIcon(TestTreeItem::Type type) { - static QIcon icons[3] = { + static QIcon icons[] = { QIcon(), QIcon(QLatin1String(":/images/class.png")), - QIcon(QLatin1String(":/images/func.png")) + QIcon(QLatin1String(":/images/func.png")), + QIcon(QLatin1String(":/images/data.png")) }; - if (type >= 3) + if (type >= sizeof(icons) / sizeof(icons[0])) return icons[2]; return icons[type]; } @@ -204,7 +205,7 @@ QVariant TestTreeModel::data(const QModelIndex &index, int role) const || (item == m_quickTestRootItem && m_quickTestRootItem->childCount() == 0)) { return QString(item->name() + tr(" (none)")); } else { - if (item->name().isEmpty()) + if (item->name().isEmpty() && item->type() == TestTreeItem::TEST_CLASS) return tr(Constants::UNNAMED_QUICKTESTS); return item->name(); } @@ -222,6 +223,7 @@ QVariant TestTreeModel::data(const QModelIndex &index, int role) const case Qt::CheckStateRole: switch (item->type()) { case TestTreeItem::ROOT: + case TestTreeItem::TEST_DATATAG: case TestTreeItem::TEST_DATAFUNCTION: case TestTreeItem::TEST_SPECIALFUNCTION: return QVariant(); @@ -682,7 +684,7 @@ void TestTreeModel::updateUnnamedQuickTest(const QString &fileName, const QStrin foreach (const QString &functionName, functions.keys()) { const TestCodeLocationAndType locationAndType = functions.value(functionName); - TestTreeItem *testFunction = new TestTreeItem(functionName, locationAndType.m_fileName, + TestTreeItem *testFunction = new TestTreeItem(functionName, locationAndType.m_name, locationAndType.m_type, &unnamed); testFunction->setLine(locationAndType.m_line); testFunction->setColumn(locationAndType.m_column); @@ -819,6 +821,19 @@ void TestTreeModel::processChildren(QModelIndex &parentIndex, const TestTreeItem TestTreeItem *modifiedChild = newItem.child(row); if (toBeModifiedChild->modifyContent(modifiedChild)) emit dataChanged(child, child, modificationRoles); + + // handle data tags - just remove old and add them + if (modifiedChild->childCount() || toBeModifiedChild->childCount()) { + beginRemoveRows(child, 0, toBeModifiedChild->childCount()); + toBeModifiedChild->removeChildren(); + endRemoveRows(); + const int count = modifiedChild->childCount(); + beginInsertRows(child, 0, count); + for (int childRow = 0; childRow < count; ++childRow) + toBeModifiedChild->appendChild(new TestTreeItem(*modifiedChild->child(childRow))); + endInsertRows(); + } + if (checkStates.contains(toBeModifiedChild->name())) { Qt::CheckState state = checkStates.value(toBeModifiedChild->name()); if (state != toBeModifiedChild->checked()) { diff --git a/plugins/autotest/testvisitor.cpp b/plugins/autotest/testvisitor.cpp index d0179c1ca72..3fe84cb0776 100644 --- a/plugins/autotest/testvisitor.cpp +++ b/plugins/autotest/testvisitor.cpp @@ -21,7 +21,6 @@ #include #include -#include #include #include @@ -29,6 +28,8 @@ #include +#include + #include namespace Autotest { @@ -73,11 +74,11 @@ bool TestVisitor::visit(CPlusPlus::Class *symbol) CPlusPlus::Function *functionDefinition = m_symbolFinder.findMatchingDefinition( func, CppTools::CppModelManager::instance()->snapshot(), true); if (functionDefinition) { - locationAndType.m_fileName = QString::fromUtf8(functionDefinition->fileName()); + locationAndType.m_name = QString::fromUtf8(functionDefinition->fileName()); locationAndType.m_line = functionDefinition->line(); locationAndType.m_column = functionDefinition->column() - 1; } else { // if we cannot find the definition use declaration as fallback - locationAndType.m_fileName = QString::fromUtf8(member->fileName()); + locationAndType.m_name = QString::fromUtf8(member->fileName()); locationAndType.m_line = member->line(); locationAndType.m_column = member->column() - 1; } @@ -145,6 +146,132 @@ bool TestAstVisitor::visit(CPlusPlus::CompoundStatementAST *ast) return true; } +/********************** Test Data Function AST Visitor ************************/ + +TestDataFunctionVisitor::TestDataFunctionVisitor(CPlusPlus::Document::Ptr doc) + : CPlusPlus::ASTVisitor(doc->translationUnit()), + m_currentDoc(doc), + m_currentAstDepth(0), + m_insideUsingQTestDepth(0), + m_insideUsingQTest(false) +{ +} + +TestDataFunctionVisitor::~TestDataFunctionVisitor() +{ +} + +bool TestDataFunctionVisitor::visit(CPlusPlus::UsingDirectiveAST *ast) +{ + if (auto nameAST = ast->name) { + if (m_overview.prettyName(nameAST->name) == QLatin1String("QTest")) { + m_insideUsingQTest = true; + // we need the surrounding AST depth as using directive is an AST itself + m_insideUsingQTestDepth = m_currentAstDepth - 1; + } + } + return true; +} + +bool TestDataFunctionVisitor::visit(CPlusPlus::FunctionDefinitionAST *ast) +{ + if (ast->declarator) { + CPlusPlus::DeclaratorIdAST *id = ast->declarator->core_declarator->asDeclaratorId(); + if (!id) + return false; + + const QString prettyName = m_overview.prettyName(id->name->name); + // do not handle functions that aren't real test data functions + if (!prettyName.endsWith(QLatin1String("_data")) || !ast->symbol + || ast->symbol->argumentCount() != 0) { + return false; + } + + m_currentFunction = prettyName.left(prettyName.size() - 5); + m_currentTags.clear(); + return true; + } + + return false; +} + +bool TestDataFunctionVisitor::visit(CPlusPlus::CallAST *ast) +{ + if (m_currentFunction.isEmpty()) + return true; + + unsigned firstToken; + if (newRowCallFound(ast, &firstToken)) { + if (const auto expressionListAST = ast->expression_list) { + // first argument is the one we need + if (const auto argumentExpressionAST = expressionListAST->value) { + if (const auto stringLiteral = argumentExpressionAST->asStringLiteral()) { + auto token = m_currentDoc->translationUnit()->tokenAt( + stringLiteral->literal_token); + if (token.isStringLiteral()) { + unsigned line = 0; + unsigned column = 0; + m_currentDoc->translationUnit()->getTokenStartPosition( + firstToken, &line, &column); + TestCodeLocationAndType locationAndType; + locationAndType.m_name = QString::fromUtf8(token.spell()); + locationAndType.m_column = column - 1; + locationAndType.m_line = line; + locationAndType.m_type = TestTreeItem::TEST_DATATAG; + m_currentTags.append(locationAndType); + } + } + } + } + } + return true; +} + +bool TestDataFunctionVisitor::preVisit(CPlusPlus::AST *) +{ + ++m_currentAstDepth; + return true; +} + +void TestDataFunctionVisitor::postVisit(CPlusPlus::AST *ast) +{ + --m_currentAstDepth; + m_insideUsingQTest &= m_currentAstDepth >= m_insideUsingQTestDepth; + + if (!ast->asFunctionDefinition()) + return; + + if (!m_currentFunction.isEmpty() && !m_currentTags.isEmpty()) + m_dataTags.insert(m_currentFunction, m_currentTags); + + m_currentFunction.clear(); + m_currentTags.clear(); +} + +bool TestDataFunctionVisitor::newRowCallFound(CPlusPlus::CallAST *ast, unsigned *firstToken) const +{ + QTC_ASSERT(firstToken, return false); + + if (!ast->base_expression) + return false; + + bool found = false; + + if (const CPlusPlus::IdExpressionAST *exp = ast->base_expression->asIdExpression()) { + if (!exp->name) + return false; + + if (const auto qualifiedNameAST = exp->name->asQualifiedName()) { + found = m_overview.prettyName(qualifiedNameAST->name) == QLatin1String("QTest::newRow"); + *firstToken = qualifiedNameAST->firstToken(); + } else if (m_insideUsingQTest) { + found = m_overview.prettyName(exp->name->name) == QLatin1String("newRow"); + *firstToken = exp->name->firstToken(); + } + } + return found; +} + /*************************** Quick Test AST Visitor ***************************/ TestQmlVisitor::TestQmlVisitor(QmlJS::Document::Ptr doc) @@ -164,7 +291,7 @@ bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast) m_currentTestCaseName.clear(); const auto sourceLocation = ast->firstSourceLocation(); - m_testCaseLocation.m_fileName = m_currentDoc->fileName(); + m_testCaseLocation.m_name = m_currentDoc->fileName(); m_testCaseLocation.m_line = sourceLocation.startLine; m_testCaseLocation.m_column = sourceLocation.startColumn - 1; m_testCaseLocation.m_type = TestTreeItem::TEST_CLASS; @@ -192,7 +319,7 @@ bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast) || specialFunctions.contains(name.toString())) { const auto sourceLocation = ast->firstSourceLocation(); TestCodeLocationAndType locationAndType; - locationAndType.m_fileName = m_currentDoc->fileName(); + locationAndType.m_name = m_currentDoc->fileName(); locationAndType.m_line = sourceLocation.startLine; locationAndType.m_column = sourceLocation.startColumn - 1; if (specialFunctions.contains(name.toString())) diff --git a/plugins/autotest/testvisitor.h b/plugins/autotest/testvisitor.h index 07d58352930..4441eb26f8a 100644 --- a/plugins/autotest/testvisitor.h +++ b/plugins/autotest/testvisitor.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -72,6 +73,32 @@ private: }; +class TestDataFunctionVisitor : public CPlusPlus::ASTVisitor +{ +public: + TestDataFunctionVisitor(CPlusPlus::Document::Ptr doc); + virtual ~TestDataFunctionVisitor(); + + bool visit(CPlusPlus::UsingDirectiveAST *ast); + bool visit(CPlusPlus::FunctionDefinitionAST *ast); + bool visit(CPlusPlus::CallAST *ast); + bool preVisit(CPlusPlus::AST *ast); + void postVisit(CPlusPlus::AST *ast); + QMap dataTags() const { return m_dataTags; } + +private: + bool newRowCallFound(CPlusPlus::CallAST *ast, unsigned *firstToken) const; + + CPlusPlus::Document::Ptr m_currentDoc; + CPlusPlus::Overview m_overview; + QString m_currentFunction; + QMap m_dataTags; + TestCodeLocationList m_currentTags; + unsigned m_currentAstDepth; + unsigned m_insideUsingQTestDepth; + bool m_insideUsingQTest; +}; + class TestQmlVisitor : public QmlJS::AST::Visitor { public: From 71d5142fcc65ec1af13d861660b19a84c317eafb Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 19 Aug 2015 10:22:25 +0200 Subject: [PATCH 135/200] Cache some information to speed up handling of large output Change-Id: I93c37566af029028dc40e5eb48a398eb9c7fff7c Reviewed-by: David Schulz --- plugins/autotest/testresultdelegate.cpp | 77 ++++++++++++------------- plugins/autotest/testresultdelegate.h | 9 +++ 2 files changed, 46 insertions(+), 40 deletions(-) diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp index 57dc2de8474..7cf841dd784 100644 --- a/plugins/autotest/testresultdelegate.cpp +++ b/plugins/autotest/testresultdelegate.cpp @@ -126,32 +126,15 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op } if (selected) { - int height = 0; - int leading = fm.leading(); - int fontHeight = fm.height(); output.replace(QLatin1Char('\n'), QChar::LineSeparator); if (AutotestPlugin::instance()->settings()->limitResultOutput && output.length() > outputLimit) output = output.left(outputLimit).append(QLatin1String("...")); - QTextLayout tl(output); - tl.setFont(painter->font()); - QTextOption txtOption; - txtOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); - tl.setTextOption(txtOption); - tl.beginLayout(); - while (true) { - QTextLine tLine = tl.createLine(); - if (!tLine.isValid()) - break; - tLine.setLineWidth(positions.textAreaWidth()); - height += leading; - tLine.setPosition(QPoint(0, height)); - height += fontHeight; - } - tl.endLayout(); - tl.draw(painter, QPoint(positions.textAreaLeft(), positions.top())); + recalculateTextLayout(index, output, painter->font(), positions.textAreaWidth()); + + m_lastCalculatedLayout.draw(painter, QPoint(positions.textAreaLeft(), positions.top())); } else { painter->setClipRect(positions.textArea()); // cut output before generating elided text as this takes quite long for exhaustive output @@ -234,31 +217,13 @@ QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo output.replace(QLatin1Char('\n'), QChar::LineSeparator); - int height = 0; - int leading = fm.leading(); - if (AutotestPlugin::instance()->settings()->limitResultOutput && output.length() > outputLimit) output = output.left(outputLimit).append(QLatin1String("...")); - QTextLayout tl(output); - tl.setFont(opt.font); - QTextOption txtOption; - txtOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); - tl.setTextOption(txtOption); - tl.beginLayout(); - while (true) { - QTextLine line = tl.createLine(); - if (!line.isValid()) - break; - line.setLineWidth(positions.textAreaWidth()); - height += leading; - line.setPosition(QPoint(0, height)); - height += fontHeight; - } - tl.endLayout(); + recalculateTextLayout(index, output, opt.font, positions.textAreaWidth()); - s.setHeight(height + 3); + s.setHeight(m_lastCalculatedHeight + 3); } else { s.setHeight(fontHeight + 3); } @@ -275,5 +240,37 @@ void TestResultDelegate::currentChanged(const QModelIndex ¤t, const QModel emit sizeHintChanged(previous); } +void TestResultDelegate::recalculateTextLayout(const QModelIndex &index, const QString &output, + const QFont &font, int width) const +{ + if (m_lastProcessedIndex == index && m_lastProcessedFont == font) + return; + + const QFontMetrics fm(font); + const int leading = fm.leading(); + const int fontHeight = fm.height(); + + m_lastProcessedIndex = index; + m_lastProcessedFont = font; + m_lastCalculatedHeight = 0; + m_lastCalculatedLayout.clearLayout(); + m_lastCalculatedLayout.setText(output); + m_lastCalculatedLayout.setFont(font); + QTextOption txtOption; + txtOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); + m_lastCalculatedLayout.setTextOption(txtOption); + m_lastCalculatedLayout.beginLayout(); + while (true) { + QTextLine line = m_lastCalculatedLayout.createLine(); + if (!line.isValid()) + break; + line.setLineWidth(width); + m_lastCalculatedHeight += leading; + line.setPosition(QPoint(0, m_lastCalculatedHeight)); + m_lastCalculatedHeight += fontHeight; + } + m_lastCalculatedLayout.endLayout(); +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testresultdelegate.h b/plugins/autotest/testresultdelegate.h index 0b837ed2b2b..d70b0d89029 100644 --- a/plugins/autotest/testresultdelegate.h +++ b/plugins/autotest/testresultdelegate.h @@ -23,6 +23,7 @@ #include "testresultmodel.h" #include +#include namespace Autotest { namespace Internal { @@ -41,6 +42,14 @@ public slots: void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); private: + void recalculateTextLayout(const QModelIndex &index, const QString &output, + const QFont &font, int width) const; + + mutable QModelIndex m_lastProcessedIndex; + mutable QFont m_lastProcessedFont; + mutable QTextLayout m_lastCalculatedLayout; + mutable int m_lastCalculatedHeight; + class LayoutPositions { public: From e092c5b51ddd8cd3dd6f0d32358ec4ae6198b75e Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 19 Aug 2015 13:17:55 +0200 Subject: [PATCH 136/200] Move duplicate code into function Change-Id: I48e3187acb53159c16c7884a96ebdb831571b830 Reviewed-by: Niels Weber --- plugins/autotest/testresultdelegate.cpp | 103 +++++++++--------------- plugins/autotest/testresultdelegate.h | 2 + 2 files changed, 41 insertions(+), 64 deletions(-) diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp index 7cf841dd784..4dea7c050db 100644 --- a/plugins/autotest/testresultdelegate.cpp +++ b/plugins/autotest/testresultdelegate.cpp @@ -42,6 +42,43 @@ TestResultDelegate::~TestResultDelegate() } +QString TestResultDelegate::outputString(const TestResult &testResult, bool selected) +{ + const QString desc = testResult.description(); + QString output; + switch (testResult.result()) { + case Result::PASS: + case Result::FAIL: + case Result::EXPECTED_FAIL: + case Result::UNEXPECTED_PASS: + case Result::BLACKLISTED_FAIL: + case Result::BLACKLISTED_PASS: + output = testResult.className() + QLatin1String("::") + testResult.testCase(); + if (!testResult.dataTag().isEmpty()) + output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); + if (selected && !desc.isEmpty()) { + output.append(QLatin1Char('\n')).append(desc); + } + break; + case Result::BENCHMARK: + output = testResult.className() + QLatin1String("::") + testResult.testCase(); + if (!testResult.dataTag().isEmpty()) + output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); + if (!desc.isEmpty()) { + int breakPos = desc.indexOf(QLatin1Char('(')); + output.append(QLatin1String(": ")).append(desc.left(breakPos)); + if (selected) + output.append(QLatin1Char('\n')).append(desc.mid(breakPos)); + } + break; + default: + output = desc; + if (!selected) + output = output.split(QLatin1Char('\n')).first(); + } + return output; +} + void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItemV4 opt = option; @@ -75,7 +112,6 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op TestResultModel *resultModel = static_cast(resultFilterModel->sourceModel()); LayoutPositions positions(opt, resultModel); TestResult testResult = resultModel->testResult(resultFilterModel->mapToSource(index)); - Result::Type type = testResult.result(); QIcon icon = index.data(Qt::DecorationRole).value(); if (!icon.isNull()) @@ -92,38 +128,7 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op painter->setPen(tmp); } - const QString desc = testResult.description(); - QString output; - switch (type) { - case Result::PASS: - case Result::FAIL: - case Result::EXPECTED_FAIL: - case Result::UNEXPECTED_PASS: - case Result::BLACKLISTED_FAIL: - case Result::BLACKLISTED_PASS: - output = testResult.className() + QLatin1String("::") + testResult.testCase(); - if (!testResult.dataTag().isEmpty()) - output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); - if (selected && !desc.isEmpty()) { - output.append(QLatin1Char('\n')).append(desc); - } - break; - case Result::BENCHMARK: - output = testResult.className() + QLatin1String("::") + testResult.testCase(); - if (!testResult.dataTag().isEmpty()) - output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); - if (!desc.isEmpty()) { - int breakPos = desc.indexOf(QLatin1Char('(')); - output.append(QLatin1String(": ")).append(desc.left(breakPos)); - if (selected) - output.append(QLatin1Char('\n')).append(desc.mid(breakPos)); - } - break; - default: - output = desc; - if (!selected) - output = output.split(QLatin1Char('\n')).first(); - } + QString output = outputString(testResult, selected); if (selected) { output.replace(QLatin1Char('\n'), QChar::LineSeparator); @@ -184,37 +189,7 @@ QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo if (selected) { TestResult testResult = resultModel->testResult(resultFilterModel->mapToSource(index)); - QString desc = testResult.description(); - QString output; - switch (testResult.result()) { - case Result::PASS: - case Result::FAIL: - case Result::EXPECTED_FAIL: - case Result::UNEXPECTED_PASS: - case Result::BLACKLISTED_FAIL: - case Result::BLACKLISTED_PASS: - output = testResult.className() + QLatin1String("::") + testResult.testCase(); - if (!testResult.dataTag().isEmpty()) - output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); - if (!desc.isEmpty()) { - output.append(QLatin1Char('\n')).append(desc); - } - break; - case Result::BENCHMARK: - output = testResult.className() + QLatin1String("::") + testResult.testCase(); - if (!testResult.dataTag().isEmpty()) - output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); - if (!desc.isEmpty()) { - int breakPos = desc.indexOf(QLatin1Char('(')); - output.append(QLatin1String(" - ")).append(desc.left(breakPos)); - if (selected) - output.append(QLatin1Char('\n')).append(desc.mid(breakPos)); - } - break; - default: - output = desc; - } - + QString output = outputString(testResult, selected); output.replace(QLatin1Char('\n'), QChar::LineSeparator); if (AutotestPlugin::instance()->settings()->limitResultOutput diff --git a/plugins/autotest/testresultdelegate.h b/plugins/autotest/testresultdelegate.h index d70b0d89029..63873a9d255 100644 --- a/plugins/autotest/testresultdelegate.h +++ b/plugins/autotest/testresultdelegate.h @@ -38,6 +38,8 @@ public: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + static QString outputString(const TestResult &testResult, bool selected); + public slots: void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); From 0d114c602d391f4d34146efcbdfa9f714bc5bac6 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 18 Aug 2015 10:19:28 +0200 Subject: [PATCH 137/200] Add 'Run This Test' capability to data tags Change-Id: I3eb99f0a0652053cb05a3457a37ff335bab5580b Reviewed-by: Niels Weber --- plugins/autotest/testnavigationwidget.cpp | 6 ++++-- plugins/autotest/testtreemodel.cpp | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index ad1a496b5f3..354e2869a5d 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -103,7 +103,8 @@ void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event) int type = index.data(TypeRole).toInt(); const QString &unnamed = tr(Constants::UNNAMED_QUICKTESTS); if ((type == TestTreeItem::TEST_FUNCTION && index.parent().data().toString() != unnamed) - || (type == TestTreeItem::TEST_CLASS && index.data().toString() != unnamed)) { + || (type == TestTreeItem::TEST_CLASS && index.data().toString() != unnamed) + || (type == TestTreeItem::TEST_DATATAG)) { runThisTest = new QAction(tr("Run This Test"), &menu); runThisTest->setEnabled(enabled); connect(runThisTest, &QAction::triggered, @@ -247,7 +248,8 @@ void TestNavigationWidget::onRunThisTestTriggered() return; TestTreeItem *item = static_cast(sourceIndex.internalPointer()); - if (item->type() == TestTreeItem::TEST_CLASS || item->type() == TestTreeItem::TEST_FUNCTION) { + if (item->type() == TestTreeItem::TEST_CLASS || item->type() == TestTreeItem::TEST_FUNCTION + || item->type() == TestTreeItem::TEST_DATATAG) { if (TestConfiguration *configuration = m_model->getTestConfiguration(item)) { TestRunner *runner = TestRunner::instance(); runner->setSelectedTests( {configuration} ); diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 0e3b09b4390..0b43688982c 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -558,6 +558,17 @@ TestConfiguration *TestTreeModel::getTestConfiguration(const TestTreeItem *item) } break; } + case TestTreeItem::TEST_DATATAG: { + const TestTreeItem *function = item->parent(); + const TestTreeItem *parent = function ? function->parent() : 0; + if (!parent) + return 0; + const QString functionWithTag = function->name() + QLatin1Char(':') + item->name(); + config = new TestConfiguration(parent->name(), QStringList() << functionWithTag); + config->setMainFilePath(parent->filePath()); + config->setProject(project); + break; + } // not supported items default: return 0; From 292b4847dc99f0fda01395004ed317775d89ee33 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 19 Aug 2015 13:19:28 +0200 Subject: [PATCH 138/200] Add capability to store/copy output from results pane Change-Id: Ie32a374cac851009df3d2289f471bbb697788198 Reviewed-by: Riitta-Leena Miettinen Reviewed-by: David Schulz Reviewed-by: Niels Weber --- plugins/autotest/testresultspane.cpp | 94 +++++++++++++++++++++++++++- plugins/autotest/testresultspane.h | 28 +++++++-- 2 files changed, 114 insertions(+), 8 deletions(-) diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index db78e24cd60..8f3d4f5b82c 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -28,15 +28,19 @@ #include #include #include +#include #include -#include #include +#include +#include #include +#include #include #include +#include #include #include #include @@ -44,11 +48,24 @@ namespace Autotest { namespace Internal { +ResultsTreeView::ResultsTreeView(QWidget *parent) + : Utils::TreeView(parent) +{} + +void ResultsTreeView::keyPressEvent(QKeyEvent *event) +{ + if (event->matches(QKeySequence::Copy)) { + emit copyShortcutTriggered(); + event->accept(); + } +} + TestResultsPane::TestResultsPane(QObject *parent) : Core::IOutputPane(parent), m_context(new Core::IContext(this)), m_wasVisibleBefore(false), - m_autoScroll(false) + m_autoScroll(false), + m_testRunning(false) { m_outputWidget = new QWidget; QVBoxLayout *outputLayout = new QVBoxLayout; @@ -74,9 +91,10 @@ TestResultsPane::TestResultsPane(QObject *parent) : outputLayout->addWidget(m_summaryWidget); - m_treeView = new Utils::TreeView(m_outputWidget); + m_treeView = new ResultsTreeView(m_outputWidget); m_treeView->setHeaderHidden(true); m_treeView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + m_treeView->setContextMenuPolicy(Qt::CustomContextMenu); m_model = new TestResultModel(this); m_filterModel = new TestResultFilterModel(m_model, this); m_filterModel->setDynamicSortFilter(true); @@ -91,6 +109,11 @@ TestResultsPane::TestResultsPane(QObject *parent) : connect(m_treeView, &Utils::TreeView::activated, this, &TestResultsPane::onItemActivated); connect(m_treeView->selectionModel(), &QItemSelectionModel::currentChanged, trd, &TestResultDelegate::currentChanged); + connect(m_treeView, &Utils::TreeView::customContextMenuRequested, + this, &TestResultsPane::onCustomContextMenuRequested); + connect(m_treeView, &ResultsTreeView::copyShortcutTriggered, [this] () { + onCopyItemTriggered(m_treeView->currentIndex()); + }); connect(TestRunner::instance(), &TestRunner::testRunStarted, this, &TestResultsPane::onTestRunStarted); connect(TestRunner::instance(), &TestRunner::testRunFinished, @@ -375,6 +398,7 @@ void TestResultsPane::filterMenuTriggered(QAction *action) void TestResultsPane::onTestRunStarted() { + m_testRunning = true; m_stopTestRun->setEnabled(true); m_runAll->setEnabled(false); m_runSelected->setEnabled(false); @@ -383,6 +407,7 @@ void TestResultsPane::onTestRunStarted() void TestResultsPane::onTestRunFinished() { + m_testRunning = false; m_stopTestRun->setEnabled(false); m_runAll->setEnabled(true); m_runSelected->setEnabled(true); @@ -406,5 +431,68 @@ void TestResultsPane::onTestTreeModelChanged() m_runSelected->setEnabled(enable); } +void TestResultsPane::onCustomContextMenuRequested(const QPoint &pos) +{ + const bool resultsAvailable = m_filterModel->hasResults(); + const bool enabled = !m_testRunning && resultsAvailable; + const QModelIndex clicked = m_treeView->indexAt(pos); + QMenu menu; + QAction *action = new QAction(tr("Copy"), &menu); + action->setShortcut(QKeySequence(QKeySequence::Copy)); + action->setEnabled(resultsAvailable); + connect(action, &QAction::triggered, [this, clicked] () { + onCopyItemTriggered(clicked); + }); + menu.addAction(action); + + action = new QAction(tr("Copy All"), &menu); + action->setEnabled(enabled); + connect(action, &QAction::triggered, this, &TestResultsPane::onCopyWholeTriggered); + menu.addAction(action); + + action = new QAction(tr("Save Output to File..."), &menu); + action->setEnabled(enabled); + connect(action, &QAction::triggered, this, &TestResultsPane::onSaveWholeTriggered); + menu.addAction(action); + + menu.exec(m_treeView->mapToGlobal(pos)); +} + +void TestResultsPane::onCopyItemTriggered(const QModelIndex &idx) +{ + const TestResult result = m_filterModel->testResult(idx); + QApplication::clipboard()->setText(TestResultDelegate::outputString(result, true)); +} + +void TestResultsPane::onCopyWholeTriggered() +{ + QApplication::clipboard()->setText(getWholeOutput()); +} + +void TestResultsPane::onSaveWholeTriggered() +{ + const QString fileName = QFileDialog::getSaveFileName(Core::ICore::dialogParent(), + tr("Save Output To...")); + Utils::FileSaver saver(fileName, QIODevice::Text); + if (!saver.write(getWholeOutput().toUtf8()) || !saver.finalize()) { + QMessageBox::critical(Core::ICore::dialogParent(), tr("Error"), + tr("Failed to write \"%1\".\n\n%2").arg(fileName) + .arg(saver.errorString())); + } +} + +// helper for onCopyWholeTriggered() and onSaveWholeTriggered() +QString TestResultsPane::getWholeOutput() +{ + QString output; + const QModelIndex invalid; // practically the invisible root item + for (int row = 0, count = m_model->rowCount(invalid); row < count; ++row) { + const TestResult result = m_model->testResult(m_model->index(row, 0, invalid)); + output.append(TestResult::resultToString(result.result())).append(QLatin1Char('\t')); + output.append(TestResultDelegate::outputString(result, true)).append(QLatin1Char('\n')); + } + return output; +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h index 37a35eece81..1bb3cddeddf 100644 --- a/plugins/autotest/testresultspane.h +++ b/plugins/autotest/testresultspane.h @@ -22,9 +22,12 @@ #include +#include + QT_BEGIN_NAMESPACE class QAction; class QFrame; +class QKeyEvent; class QLabel; class QModelIndex; class QMenu; @@ -35,10 +38,6 @@ namespace Core { class IContext; } -namespace Utils { -class TreeView; -} - namespace Autotest { namespace Internal { @@ -46,6 +45,19 @@ class TestResult; class TestResultModel; class TestResultFilterModel; +class ResultsTreeView : public Utils::TreeView +{ + Q_OBJECT +public: + ResultsTreeView(QWidget *parent = 0); + +signals: + void copyShortcutTriggered(); + +protected: + void keyPressEvent(QKeyEvent *event); +}; + class TestResultsPane : public Core::IOutputPane { Q_OBJECT @@ -90,11 +102,16 @@ private: void onTestRunFinished(); void onScrollBarRangeChanged(int, int max); void onTestTreeModelChanged(); + void onCustomContextMenuRequested(const QPoint &pos); + void onCopyItemTriggered(const QModelIndex &idx); + void onCopyWholeTriggered(); + void onSaveWholeTriggered(); + QString getWholeOutput(); QWidget *m_outputWidget; QFrame *m_summaryWidget; QLabel *m_summaryLabel; - Utils::TreeView *m_treeView; + ResultsTreeView *m_treeView; TestResultModel *m_model; TestResultFilterModel *m_filterModel; Core::IContext *m_context; @@ -106,6 +123,7 @@ private: bool m_wasVisibleBefore; bool m_autoScroll; bool m_atEnd; + bool m_testRunning; }; } // namespace Internal From 274d095f46fd85aecc56645bc7ce44ba0dd5a653 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 20 Aug 2015 15:59:15 +0200 Subject: [PATCH 139/200] Use QC's TreeModel for TestResultModel This changes the model to be a real tree instead of a list. Additionally the results pane now displays the results as tree as well. Change-Id: I69ba7bbfcd75ce17c3a0d4052498d9c1c7382d43 Reviewed-by: Niels Weber --- plugins/autotest/testresult.cpp | 20 ++ plugins/autotest/testresult.h | 6 + plugins/autotest/testresultdelegate.cpp | 28 +-- plugins/autotest/testresultdelegate.h | 25 +- plugins/autotest/testresultmodel.cpp | 287 ++++++++++++++--------- plugins/autotest/testresultmodel.h | 40 ++-- plugins/autotest/testresultspane.cpp | 111 +++++++-- plugins/autotest/testresultspane.h | 5 +- plugins/autotest/testrunner.cpp | 22 +- plugins/autotest/testrunner.h | 2 +- plugins/autotest/testxmloutputreader.cpp | 38 +-- plugins/autotest/testxmloutputreader.h | 2 +- 12 files changed, 371 insertions(+), 215 deletions(-) diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp index 6a054a4c7d4..0ce300eade5 100644 --- a/plugins/autotest/testresult.cpp +++ b/plugins/autotest/testresult.cpp @@ -91,6 +91,16 @@ Result::Type TestResult::toResultType(int rt) return Result::MESSAGE_FATAL; case Result::MESSAGE_INTERNAL: return Result::MESSAGE_INTERNAL; + case Result::MESSAGE_TEST_CASE_START: + return Result::MESSAGE_TEST_CASE_START; + case Result::MESSAGE_TEST_CASE_SUCCESS: + return Result::MESSAGE_TEST_CASE_SUCCESS; + case Result::MESSAGE_TEST_CASE_WARN: + return Result::MESSAGE_TEST_CASE_WARN; + case Result::MESSAGE_TEST_CASE_FAIL: + return Result::MESSAGE_TEST_CASE_FAIL; + case Result::MESSAGE_TEST_CASE_END: + return Result::MESSAGE_TEST_CASE_END; case Result::MESSAGE_CURRENT_TEST: return Result::MESSAGE_CURRENT_TEST; default: @@ -120,6 +130,11 @@ QString TestResult::resultToString(const Result::Type type) case Result::MESSAGE_FATAL: return QLatin1String("FATAL"); case Result::MESSAGE_INTERNAL: + case Result::MESSAGE_TEST_CASE_START: + case Result::MESSAGE_TEST_CASE_SUCCESS: + case Result::MESSAGE_TEST_CASE_WARN: + case Result::MESSAGE_TEST_CASE_FAIL: + case Result::MESSAGE_TEST_CASE_END: case Result::MESSAGE_CURRENT_TEST: return QString(); case Result::BLACKLISTED_PASS: @@ -155,6 +170,11 @@ QColor TestResult::colorForType(const Result::Type type) case Result::MESSAGE_FATAL: return QColor("#640000"); case Result::MESSAGE_INTERNAL: + case Result::MESSAGE_TEST_CASE_START: + case Result::MESSAGE_TEST_CASE_SUCCESS: + case Result::MESSAGE_TEST_CASE_WARN: + case Result::MESSAGE_TEST_CASE_FAIL: + case Result::MESSAGE_TEST_CASE_END: case Result::MESSAGE_CURRENT_TEST: return QColor("transparent"); default: diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index c1d6d5eac42..e1e6e770d0e 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -41,6 +41,11 @@ enum Type { MESSAGE_WARN, MESSAGE_FATAL, MESSAGE_INTERNAL, + MESSAGE_TEST_CASE_START, + MESSAGE_TEST_CASE_SUCCESS, + MESSAGE_TEST_CASE_WARN, + MESSAGE_TEST_CASE_FAIL, + MESSAGE_TEST_CASE_END, MESSAGE_CURRENT_TEST, UNKNOWN // ??? }; @@ -65,6 +70,7 @@ public: void setDescription(const QString &description) { m_description = description; } void setFileName(const QString &fileName) { m_file = fileName; } void setLine(int line) { m_line = line; } + void setResult(Result::Type type) { m_result = type; } static Result::Type resultFromString(const QString &resultString); static Result::Type toResultType(int rt); diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp index 4dea7c050db..b123c99db9d 100644 --- a/plugins/autotest/testresultdelegate.cpp +++ b/plugins/autotest/testresultdelegate.cpp @@ -37,11 +37,6 @@ TestResultDelegate::TestResultDelegate(QObject *parent) { } -TestResultDelegate::~TestResultDelegate() -{ - -} - QString TestResultDelegate::outputString(const TestResult &testResult, bool selected) { const QString desc = testResult.description(); @@ -88,7 +83,6 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op painter->save(); QFontMetrics fm(opt.font); - QColor background; QColor foreground; const QAbstractItemView *view = qobject_cast(opt.widget); @@ -96,22 +90,23 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op if (selected) { painter->setBrush(opt.palette.highlight().color()); - background = opt.palette.highlight().color(); foreground = opt.palette.highlightedText().color(); } else { painter->setBrush(opt.palette.background().color()); - background = opt.palette.background().color(); foreground = opt.palette.text().color(); } - painter->setPen(Qt::NoPen); painter->drawRect(opt.rect); - painter->setPen(foreground); + TestResultFilterModel *resultFilterModel = static_cast(view->model()); - TestResultModel *resultModel = static_cast(resultFilterModel->sourceModel()); - LayoutPositions positions(opt, resultModel); - TestResult testResult = resultModel->testResult(resultFilterModel->mapToSource(index)); + LayoutPositions positions(opt, resultFilterModel); + const TestResult &testResult = resultFilterModel->testResult(index); + + // draw the indicator by ourself as we paint across it with the delegate + QStyleOptionViewItemV4 indicatorOpt = option; + indicatorOpt.rect = QRect(0, opt.rect.y(), positions.indentation(), opt.rect.height()); + opt.widget->style()->drawPrimitive(QStyle::PE_IndicatorBranch, &indicatorOpt, painter); QIcon icon = index.data(Qt::DecorationRole).value(); if (!icon.isNull()) @@ -163,7 +158,7 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op } painter->setClipRect(opt.rect); - painter->setPen(QColor::fromRgb(150, 150, 150)); + painter->setPen(opt.palette.midlight().color()); painter->drawLine(0, opt.rect.bottom(), opt.rect.right(), opt.rect.bottom()); painter->restore(); } @@ -181,13 +176,12 @@ QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo QFontMetrics fm(opt.font); int fontHeight = fm.height(); TestResultFilterModel *resultFilterModel = static_cast(view->model()); - TestResultModel *resultModel = static_cast(resultFilterModel->sourceModel()); - LayoutPositions positions(opt, resultModel); + LayoutPositions positions(opt, resultFilterModel); QSize s; s.setWidth(opt.rect.width()); if (selected) { - TestResult testResult = resultModel->testResult(resultFilterModel->mapToSource(index)); + const TestResult &testResult = resultFilterModel->testResult(index); QString output = outputString(testResult, selected); output.replace(QLatin1Char('\n'), QChar::LineSeparator); diff --git a/plugins/autotest/testresultdelegate.h b/plugins/autotest/testresultdelegate.h index 63873a9d255..9df661ab5b5 100644 --- a/plugins/autotest/testresultdelegate.h +++ b/plugins/autotest/testresultdelegate.h @@ -33,7 +33,6 @@ class TestResultDelegate : public QStyledItemDelegate Q_OBJECT public: explicit TestResultDelegate(QObject *parent = 0); - ~TestResultDelegate(); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; @@ -55,15 +54,19 @@ private: class LayoutPositions { public: - LayoutPositions(QStyleOptionViewItemV4 &options, TestResultModel *model) + LayoutPositions(QStyleOptionViewItemV4 &options, TestResultFilterModel *filterModel) : m_totalWidth(options.rect.width()), - m_maxFileLength(model->maxWidthOfFileName(options.font)), - m_maxLineLength(model->maxWidthOfLineNumber(options.font)), - m_realFileLength(m_maxFileLength), m_top(options.rect.top()), m_bottom(options.rect.bottom()) { + TestResultModel *srcModel = static_cast(filterModel->sourceModel()); + m_maxFileLength = srcModel->maxWidthOfFileName(options.font); + m_maxLineLength = srcModel->maxWidthOfLineNumber(options.font); + m_realFileLength = m_maxFileLength; m_typeAreaWidth = QFontMetrics(options.font).width(QLatin1String("XXXXXXXX")); + m_indentation = options.widget ? options.widget->style()->pixelMetric( + QStyle::PM_TreeViewIndentation, &options) : 0; + m_level = srcModel->hasChildren(filterModel->mapToSource(options.index)) ? 1 : 2; int flexibleArea = lineAreaLeft() - textAreaLeft() - ITEM_SPACING; if (m_maxFileLength > flexibleArea / 2) m_realFileLength = flexibleArea / 2; @@ -71,7 +74,7 @@ private: } int top() const { return m_top + ITEM_MARGIN; } - int left() const { return ITEM_MARGIN; } + int left() const { return ITEM_MARGIN + m_indentation * m_level; } int right() const { return m_totalWidth - ITEM_MARGIN; } int bottom() const { return m_bottom; } int minimumHeight() const { return ICON_SIZE + 2 * ITEM_MARGIN; } @@ -80,17 +83,19 @@ private: int fontHeight() const { return m_fontHeight; } int typeAreaLeft() const { return left() + ICON_SIZE + ITEM_SPACING; } int typeAreaWidth() const { return m_typeAreaWidth; } - int textAreaLeft() const { return typeAreaLeft() + m_typeAreaWidth + ITEM_SPACING; } + int textAreaLeft() const { return typeAreaLeft() + m_typeAreaWidth + ITEM_SPACING + + (1 - m_level) * m_indentation; } int textAreaWidth() const { return fileAreaLeft() - ITEM_SPACING - textAreaLeft(); } int fileAreaLeft() const { return lineAreaLeft() - ITEM_SPACING - m_realFileLength; } int lineAreaLeft() const { return right() - m_maxLineLength; } + int indentation() const { return m_indentation; } QRect typeArea() const { return QRect(typeAreaLeft(), top(), typeAreaWidth(), m_fontHeight); } QRect textArea() const { return QRect(textAreaLeft(), top(), - fileAreaLeft() - ITEM_SPACING, m_fontHeight); } + textAreaWidth(), m_fontHeight); } QRect fileArea() const { return QRect(fileAreaLeft(), top(), - lineAreaLeft() - ITEM_SPACING, m_fontHeight); } + m_realFileLength + ITEM_SPACING, m_fontHeight); } QRect lineArea() const { return QRect(lineAreaLeft(), top(), m_maxLineLength, m_fontHeight); } @@ -104,6 +109,8 @@ private: int m_bottom; int m_fontHeight; int m_typeAreaWidth; + int m_level; + int m_indentation; static const int ICON_SIZE = 16; static const int ITEM_MARGIN = 2; diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index ee104700326..dd46554043c 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -19,47 +19,22 @@ #include "testresultmodel.h" -#include #include #include -#include namespace Autotest { namespace Internal { -TestResultModel::TestResultModel(QObject *parent) : - QAbstractItemModel(parent), - m_widthOfLineNumber(0), - m_maxWidthOfFileName(0), - m_lastMaxWidthIndex(0) +/********************************* TestResultItem ******************************************/ + +TestResultItem::TestResultItem(TestResult *testResult) + : m_testResult(testResult) { } -TestResultModel::~TestResultModel() +TestResultItem::~TestResultItem() { - m_testResults.clear(); -} - -QModelIndex TestResultModel::index(int row, int column, const QModelIndex &parent) const -{ - if (parent.isValid()) - return QModelIndex(); - return createIndex(row, column); -} - -QModelIndex TestResultModel::parent(const QModelIndex &) const -{ - return QModelIndex(); -} - -int TestResultModel::rowCount(const QModelIndex &parent) const -{ - return parent.isValid() ? 0 : m_testResults.size(); -} - -int TestResultModel::columnCount(const QModelIndex &parent) const -{ - return parent.isValid() ? 0 : 1; + delete m_testResult; } static QIcon testResultIcon(Result::Type result) { @@ -77,116 +52,201 @@ static QIcon testResultIcon(Result::Type result) { QIcon(QLatin1String(":/images/fatal.png")), }; // provide an icon for unknown?? - if (result < 0 || result >= Result::MESSAGE_INTERNAL) - return QIcon(); + if (result < 0 || result >= Result::MESSAGE_INTERNAL) { + switch (result) { + case Result::MESSAGE_TEST_CASE_SUCCESS: + return icons[Result::PASS]; + case Result::MESSAGE_TEST_CASE_FAIL: + return icons[Result::FAIL]; + case Result::MESSAGE_TEST_CASE_WARN: + return icons[Result::MESSAGE_WARN]; + default: + return QIcon(); + } + } return icons[result]; } -QVariant TestResultModel::data(const QModelIndex &index, int role) const +QVariant TestResultItem::data(int column, int role) const { - if (!index.isValid() || index.row() >= m_testResults.count() || index.column() != 0) - return QVariant(); - if (role == Qt::DisplayRole) { - const TestResult &tr = m_testResults.at(index.row()); - switch (tr.result()) { - case Result::PASS: - case Result::FAIL: - case Result::EXPECTED_FAIL: - case Result::UNEXPECTED_PASS: - case Result::SKIP: - case Result::BLACKLISTED_PASS: - case Result::BLACKLISTED_FAIL: - case Result::BENCHMARK: - return QString::fromLatin1("%1::%2 (%3) - %4").arg(tr.className(), tr.testCase(), - tr.dataTag(), tr.fileName()); - default: - return tr.description(); + if (role == Qt::DecorationRole) + return m_testResult ? testResultIcon(m_testResult->result()) : QVariant(); + + return Utils::TreeItem::data(column, role); +} + +void TestResultItem::updateDescription(const QString &description) +{ + QTC_ASSERT(m_testResult, return); + + m_testResult->setDescription(description); +} + +void TestResultItem::updateResult() +{ + if (m_testResult->result() != Result::MESSAGE_TEST_CASE_START) + return; + + Result::Type newResult = Result::MESSAGE_TEST_CASE_SUCCESS; + foreach (Utils::TreeItem *child, children()) { + const TestResult *current = static_cast(child)->testResult(); + if (current) { + switch (current->result()) { + case Result::FAIL: + case Result::MESSAGE_FATAL: + case Result::UNEXPECTED_PASS: + m_testResult->setResult(Result::MESSAGE_TEST_CASE_FAIL); + return; + case Result::EXPECTED_FAIL: + case Result::MESSAGE_WARN: + case Result::SKIP: + case Result::BLACKLISTED_FAIL: + case Result::BLACKLISTED_PASS: + newResult = Result::MESSAGE_TEST_CASE_WARN; + break; + default: {} + } } } - if (role == Qt::DecorationRole) { - const TestResult &tr = m_testResults.at(index.row()); - return testResultIcon(tr.result()); - } + m_testResult->setResult(newResult); +} + +/********************************* TestResultModel *****************************************/ + +TestResultModel::TestResultModel(QObject *parent) + : Utils::TreeModel(parent), + m_widthOfLineNumber(0), + m_maxWidthOfFileName(0) +{ +} + +QVariant TestResultModel::data(const QModelIndex &idx, int role) const +{ + if (!idx.isValid()) + return QVariant(); + + if (role == Qt::DecorationRole) + return itemForIndex(idx)->data(0, Qt::DecorationRole); return QVariant(); } -void TestResultModel::addTestResult(const TestResult &testResult) +void TestResultModel::addTestResult(TestResult *testResult, bool autoExpand) { - const bool isCurrentTestMssg = testResult.result() == Result::MESSAGE_CURRENT_TEST; - TestResult lastMssg = m_testResults.empty() ? TestResult() : m_testResults.last(); - - int position = m_testResults.size(); - - if (isCurrentTestMssg && lastMssg.result() == Result::MESSAGE_CURRENT_TEST) { - lastMssg.setDescription(testResult.description()); - m_testResults.replace(m_testResults.size() - 1, lastMssg); - const QModelIndex changed = index(m_testResults.size() - 1, 0, QModelIndex()); - emit dataChanged(changed, changed); - } else { - if (!isCurrentTestMssg && position) // decrement only if at least one other item - --position; - beginInsertRows(QModelIndex(), position, position); - m_testResults.insert(position, testResult); - endInsertRows(); - } + const bool isCurrentTestMssg = testResult->result() == Result::MESSAGE_CURRENT_TEST; + QVector topLevelItems = rootItem()->children(); + int lastRow = topLevelItems.size() - 1; + TestResultItem *newItem = new TestResultItem(testResult); + // we'll add the new item, so raising it's counter if (!isCurrentTestMssg) { - int count = m_testResultCount.value(testResult.result(), 0); - m_testResultCount.insert(testResult.result(), ++count); + int count = m_testResultCount.value(testResult->result(), 0); + m_testResultCount.insert(testResult->result(), ++count); + } else { + // MESSAGE_CURRENT_TEST should always be the last top level item + if (lastRow >= 0) { + TestResultItem *current = static_cast(topLevelItems.at(lastRow)); + const TestResult *result = current->testResult(); + if (result && result->result() == Result::MESSAGE_CURRENT_TEST) { + current->updateDescription(testResult->description()); + emit dataChanged(current->index(), current->index()); + return; + } + } + + rootItem()->appendChild(newItem); + return; } + + // FIXME this might be totally wrong... we need some more unique information! + for (int row = lastRow; row >= 0; --row) { + TestResultItem *current = static_cast(topLevelItems.at(row)); + const TestResult *result = current->testResult(); + if (result && result->className() == testResult->className()) { + current->appendChild(newItem); + if (autoExpand) + current->expand(); + if (testResult->result() == Result::MESSAGE_TEST_CASE_END) { + current->updateResult(); + emit dataChanged(current->index(), current->index()); + } + return; + } + } + // if we have a MESSAGE_CURRENT_TEST present, add the new top level item before it + if (lastRow >= 0) { + TestResultItem *current = static_cast(topLevelItems.at(lastRow)); + const TestResult *result = current->testResult(); + if (result && result->result() == Result::MESSAGE_CURRENT_TEST) { + rootItem()->insertChild(current->index().row(), newItem); + return; + } + } + + rootItem()->appendChild(newItem); } void TestResultModel::removeCurrentTestMessage() { - TestResult lastMssg = m_testResults.empty() ? TestResult() : m_testResults.last(); - if (lastMssg.result() == Result::MESSAGE_CURRENT_TEST) { - beginRemoveRows(QModelIndex(), m_testResults.size() - 1, m_testResults.size() - 1); - m_testResults.removeLast(); - endRemoveRows(); + QVector topLevelItems = rootItem()->children(); + for (int row = topLevelItems.size() - 1; row >= 0; --row) { + TestResultItem *current = static_cast(topLevelItems.at(row)); + if (current->testResult()->result() == Result::MESSAGE_CURRENT_TEST) { + delete takeItem(current); + break; + } } } void TestResultModel::clearTestResults() { - if (m_testResults.size() == 0) - return; - beginRemoveRows(QModelIndex(), 0, m_testResults.size() - 1); - m_testResults.clear(); + clear(); m_testResultCount.clear(); - m_lastMaxWidthIndex = 0; + m_processedIndices.clear(); m_maxWidthOfFileName = 0; m_widthOfLineNumber = 0; - endRemoveRows(); } -TestResult TestResultModel::testResult(const QModelIndex &index) const +TestResult TestResultModel::testResult(const QModelIndex &idx) { - if (!index.isValid()) - return TestResult(QString(), QString()); - return m_testResults.at(index.row()); + if (idx.isValid()) + return *(static_cast(itemForIndex(idx))->testResult()); + + return TestResult(); } int TestResultModel::maxWidthOfFileName(const QFont &font) { - int count = m_testResults.size(); - if (count == 0) - return 0; - if (m_maxWidthOfFileName > 0 && font == m_measurementFont && m_lastMaxWidthIndex == count - 1) - return m_maxWidthOfFileName; - - QFontMetrics fm(font); - m_measurementFont = font; - - for (int i = m_lastMaxWidthIndex; i < count; ++i) { - QString filename = m_testResults.at(i).fileName(); - const int pos = filename.lastIndexOf(QLatin1Char('/')); - if (pos != -1) - filename = filename.mid(pos +1); - - m_maxWidthOfFileName = qMax(m_maxWidthOfFileName, fm.width(filename)); + if (font != m_measurementFont) { + m_processedIndices.clear(); + m_maxWidthOfFileName = 0; + m_measurementFont = font; + } + + const QFontMetrics fm(font); + const QVector &topLevelItems = rootItem()->children(); + const int count = topLevelItems.size(); + for (int row = 0; row < count; ++row) { + int processed = row < m_processedIndices.size() ? m_processedIndices.at(row) : 0; + const QVector &children = topLevelItems.at(row)->children(); + const int itemCount = children.size(); + if (processed < itemCount) { + for (int childRow = processed; childRow < itemCount; ++childRow) { + const TestResultItem *item = static_cast(children.at(childRow)); + if (const TestResult *result = item->testResult()) { + QString fileName = result->fileName(); + const int pos = fileName.lastIndexOf(QLatin1Char('/')); + if (pos != -1) + fileName = fileName.mid(pos + 1); + m_maxWidthOfFileName = qMax(m_maxWidthOfFileName, fm.width(fileName)); + } + } + if (row < m_processedIndices.size()) + m_processedIndices.replace(row, itemCount); + else + m_processedIndices.insert(row, itemCount); + } } - m_lastMaxWidthIndex = count - 1; return m_maxWidthOfFileName; } @@ -200,11 +260,6 @@ int TestResultModel::maxWidthOfLineNumber(const QFont &font) return m_widthOfLineNumber; } -int TestResultModel::resultTypeCount(Result::Type type) -{ - return m_testResultCount.value(type, 0); -} - /********************************** Filter Model **********************************/ TestResultFilterModel::TestResultFilterModel(TestResultModel *sourceModel, QObject *parent) @@ -222,7 +277,9 @@ void TestResultFilterModel::enableAllResultTypes() << Result::MESSAGE_WARN << Result::MESSAGE_INTERNAL << Result::MESSAGE_FATAL << Result::UNKNOWN << Result::BLACKLISTED_PASS << Result::BLACKLISTED_FAIL << Result::BENCHMARK - << Result::MESSAGE_CURRENT_TEST; + << Result::MESSAGE_CURRENT_TEST << Result::MESSAGE_TEST_CASE_START + << Result::MESSAGE_TEST_CASE_SUCCESS << Result::MESSAGE_TEST_CASE_WARN + << Result::MESSAGE_TEST_CASE_FAIL << Result::MESSAGE_TEST_CASE_END; invalidateFilter(); } @@ -230,8 +287,12 @@ void TestResultFilterModel::toggleTestResultType(Result::Type type) { if (m_enabled.contains(type)) { m_enabled.remove(type); + if (type == Result::MESSAGE_INTERNAL) + m_enabled.remove(Result::MESSAGE_TEST_CASE_END); } else { m_enabled.insert(type); + if (type == Result::MESSAGE_INTERNAL) + m_enabled.insert(Result::MESSAGE_TEST_CASE_END); } invalidateFilter(); } diff --git a/plugins/autotest/testresultmodel.h b/plugins/autotest/testresultmodel.h index 97f3a3a53ce..5a108aa45ca 100644 --- a/plugins/autotest/testresultmodel.h +++ b/plugins/autotest/testresultmodel.h @@ -27,43 +27,47 @@ #include #include +#include + namespace Autotest { namespace Internal { -class TestResultModel : public QAbstractItemModel +class TestResultItem : public Utils::TreeItem +{ +public: + explicit TestResultItem(TestResult *testResult); + ~TestResultItem(); + QVariant data(int column, int role) const; + const TestResult *testResult() const { return m_testResult; } + void updateDescription(const QString &description); + void updateResult(); + +private: + TestResult *m_testResult; +}; + +class TestResultModel : public Utils::TreeModel { - Q_OBJECT public: explicit TestResultModel(QObject *parent = 0); - ~TestResultModel(); - QModelIndex index(int row, int column, const QModelIndex &parent) const; - QModelIndex parent(const QModelIndex &) const; - int rowCount(const QModelIndex &parent) const; - int columnCount(const QModelIndex &parent) const; - QVariant data(const QModelIndex &index, int role) const; + QVariant data(const QModelIndex &idx, int role) const; - void addTestResult(const TestResult &testResult); + void addTestResult(TestResult *testResult, bool autoExpand = false); void removeCurrentTestMessage(); void clearTestResults(); - bool hasResults() const { return m_testResults.size() > 0; } - TestResult testResult(const QModelIndex &index) const; + TestResult testResult(const QModelIndex &idx); int maxWidthOfFileName(const QFont &font); int maxWidthOfLineNumber(const QFont &font); - int resultTypeCount(Result::Type type); - -signals: - -public slots: + int resultTypeCount(Result::Type type) const { return m_testResultCount.value(type, 0); } private: - QList m_testResults; QMap m_testResultCount; int m_widthOfLineNumber; int m_maxWidthOfFileName; - int m_lastMaxWidthIndex; + QList m_processedIndices; QFont m_measurementFont; }; diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 8f3d4f5b82c..c971321333c 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -114,6 +114,9 @@ TestResultsPane::TestResultsPane(QObject *parent) : connect(m_treeView, &ResultsTreeView::copyShortcutTriggered, [this] () { onCopyItemTriggered(m_treeView->currentIndex()); }); + connect(m_model, &TestResultModel::requestExpansion, [this] (QModelIndex idx) { + m_treeView->expand(m_filterModel->mapFromSource(idx)); + }); connect(TestRunner::instance(), &TestRunner::testRunStarted, this, &TestResultsPane::onTestRunStarted); connect(TestRunner::instance(), &TestRunner::testRunFinished, @@ -122,6 +125,18 @@ TestResultsPane::TestResultsPane(QObject *parent) : void TestResultsPane::createToolButtons() { + m_expandCollapse = new QToolButton(m_treeView); + m_expandCollapse->setIcon(QIcon(QLatin1String(":/find/images/expand.png"))); + m_expandCollapse->setToolTip(tr("Expand All")); + m_expandCollapse->setCheckable(true); + m_expandCollapse->setChecked(false); + connect(m_expandCollapse, &QToolButton::clicked, [this] (bool checked) { + if (checked) + m_treeView->expandAll(); + else + m_treeView->collapseAll(); + }); + m_runAll = new QToolButton(m_treeView); m_runAll->setIcon(QIcon(QLatin1String(":/images/run.png"))); m_runAll->setToolTip(tr("Run All Tests")); @@ -167,12 +182,12 @@ TestResultsPane::~TestResultsPane() m_instance = 0; } -void TestResultsPane::addTestResult(const TestResult &result) +void TestResultsPane::addTestResult(TestResult *result) { const QScrollBar *scrollBar = m_treeView->verticalScrollBar(); m_atEnd = scrollBar ? scrollBar->value() == scrollBar->maximum() : true; - m_model->addTestResult(result); + m_model->addTestResult(result, m_expandCollapse->isChecked()); if (!m_treeView->isVisible()) popup(Core::IOutputPane::NoModeSwitch); flash(); @@ -191,7 +206,8 @@ QWidget *TestResultsPane::outputWidget(QWidget *parent) QList TestResultsPane::toolBarWidgets() const { - return QList() << m_runAll << m_runSelected << m_stopTestRun << m_filterButton; + return QList() << m_expandCollapse << m_runAll << m_runSelected << m_stopTestRun + << m_filterButton; } QString TestResultsPane::displayName() const @@ -266,17 +282,41 @@ void TestResultsPane::goToNext() if (!canNext()) return; - QModelIndex currentIndex = m_treeView->currentIndex(); + const QModelIndex currentIndex = m_treeView->currentIndex(); + QModelIndex nextCurrentIndex; + if (currentIndex.isValid()) { - int row = currentIndex.row() + 1; - if (row == m_filterModel->rowCount(QModelIndex())) - row = 0; - currentIndex = m_filterModel->index(row, 0, QModelIndex()); - } else { - currentIndex = m_filterModel->index(0, 0, QModelIndex()); + // try to set next to first child or next sibling + if (m_filterModel->rowCount(currentIndex)) { + nextCurrentIndex = currentIndex.child(0, 0); + } else { + nextCurrentIndex = currentIndex.sibling(currentIndex.row() + 1, 0); + // if it had no sibling check siblings of parent (and grandparents if necessary) + if (!nextCurrentIndex.isValid()) { + + QModelIndex parent = currentIndex.parent(); + do { + if (!parent.isValid()) + break; + nextCurrentIndex = parent.sibling(parent.row() + 1, 0); + parent = parent.parent(); + } while (!nextCurrentIndex.isValid()); + } + } } - m_treeView->setCurrentIndex(currentIndex); - onItemActivated(currentIndex); + + // if we have no current or could not find a next one, use the first item of the whole tree + if (!nextCurrentIndex.isValid()) { + Utils::TreeItem *rootItem = m_model->itemForIndex(QModelIndex()); + // if the tree does not contain any item - don't do anything + if (!rootItem || !rootItem->childCount()) + return; + + nextCurrentIndex = m_filterModel->mapFromSource(m_model->indexForItem(rootItem->child(0))); + } + + m_treeView->setCurrentIndex(nextCurrentIndex); + onItemActivated(nextCurrentIndex); } void TestResultsPane::goToPrev() @@ -284,17 +324,37 @@ void TestResultsPane::goToPrev() if (!canPrevious()) return; - QModelIndex currentIndex = m_treeView->currentIndex(); + const QModelIndex currentIndex = m_treeView->currentIndex(); + QModelIndex nextCurrentIndex; + if (currentIndex.isValid()) { - int row = currentIndex.row() - 1; - if (row < 0) - row = m_filterModel->rowCount(QModelIndex()) - 1; - currentIndex = m_filterModel->index(row, 0, QModelIndex()); - } else { - currentIndex = m_filterModel->index(m_filterModel->rowCount(QModelIndex()) - 1, 0, QModelIndex()); + // try to set next to prior sibling or parent + if (currentIndex.row() > 0) { + nextCurrentIndex = currentIndex.sibling(currentIndex.row() - 1, 0); + // if the sibling has children, use the last one + while (int rowCount = m_filterModel->rowCount(nextCurrentIndex)) + nextCurrentIndex = nextCurrentIndex.child(rowCount - 1, 0); + } else { + nextCurrentIndex = currentIndex.parent(); + } } - m_treeView->setCurrentIndex(currentIndex); - onItemActivated(currentIndex); + + // if we have no current or didn't find a sibling/parent use the last item of the whole tree + if (!nextCurrentIndex.isValid()) { + const QModelIndex rootIdx = m_filterModel->index(0, 0); + // if the tree does not contain any item - don't do anything + if (!rootIdx.isValid()) + return; + + // get the last (visible) top level index + nextCurrentIndex = m_filterModel->index(m_filterModel->rowCount(QModelIndex()) - 1, 0); + // step through until end + while (int rowCount = m_filterModel->rowCount(nextCurrentIndex)) + nextCurrentIndex = nextCurrentIndex.child(rowCount - 1, 0); + } + + m_treeView->setCurrentIndex(nextCurrentIndex); + onItemActivated(nextCurrentIndex); } void TestResultsPane::onItemActivated(const QModelIndex &index) @@ -482,14 +542,15 @@ void TestResultsPane::onSaveWholeTriggered() } // helper for onCopyWholeTriggered() and onSaveWholeTriggered() -QString TestResultsPane::getWholeOutput() +QString TestResultsPane::getWholeOutput(const QModelIndex &parent) { QString output; - const QModelIndex invalid; // practically the invisible root item - for (int row = 0, count = m_model->rowCount(invalid); row < count; ++row) { - const TestResult result = m_model->testResult(m_model->index(row, 0, invalid)); + for (int row = 0, count = m_model->rowCount(parent); row < count; ++row) { + QModelIndex current = m_model->index(row, 0, parent); + const TestResult result = m_model->testResult(current); output.append(TestResult::resultToString(result.result())).append(QLatin1Char('\t')); output.append(TestResultDelegate::outputString(result, true)).append(QLatin1Char('\n')); + output.append(getWholeOutput(current)); } return output; } diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h index 1bb3cddeddf..5fbb71413e2 100644 --- a/plugins/autotest/testresultspane.h +++ b/plugins/autotest/testresultspane.h @@ -84,7 +84,7 @@ public: signals: public slots: - void addTestResult(const TestResult &result); + void addTestResult(TestResult *result); private slots: void onItemActivated(const QModelIndex &index); @@ -106,7 +106,7 @@ private: void onCopyItemTriggered(const QModelIndex &idx); void onCopyWholeTriggered(); void onSaveWholeTriggered(); - QString getWholeOutput(); + QString getWholeOutput(const QModelIndex &parent = QModelIndex()); QWidget *m_outputWidget; QFrame *m_summaryWidget; @@ -115,6 +115,7 @@ private: TestResultModel *m_model; TestResultFilterModel *m_filterModel; Core::IContext *m_context; + QToolButton *m_expandCollapse; QToolButton *m_runAll; QToolButton *m_runSelected; QToolButton *m_stopTestRun; diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index b556989d625..ea26b0e75f0 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -43,7 +43,7 @@ namespace Internal { static TestRunner *m_instance = 0; -void emitTestResultCreated(const TestResult &testResult) +void emitTestResultCreated(TestResult *testResult) { emit m_instance->testResultCreated(testResult); } @@ -114,7 +114,7 @@ void performTestRun(QFutureInterface &futureInterface, if (config->project()) { testCaseCount += config->testCaseCount(); } else { - emitTestResultCreated(FaultyTestResult(Result::MESSAGE_WARN, + emitTestResultCreated(new FaultyTestResult(Result::MESSAGE_WARN, QObject::tr("Project is null for \"%1\". Removing from test run.\n" "Check the test environment.").arg(config->displayName()))); } @@ -148,7 +148,7 @@ void performTestRun(QFutureInterface &futureInterface, QProcessEnvironment environment = testConfiguration->environment().toProcessEnvironment(); QString commandFilePath = executableFilePath(testConfiguration->targetFile(), environment); if (commandFilePath.isEmpty()) { - emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, + emitTestResultCreated(new FaultyTestResult(Result::MESSAGE_FATAL, QObject::tr("Could not find command \"%1\". (%2)") .arg(testConfiguration->targetFile()) .arg(testConfiguration->displayName()))); @@ -177,8 +177,8 @@ void performTestRun(QFutureInterface &futureInterface, if (futureInterface.isCanceled()) { testProcess.kill(); testProcess.waitForFinished(); - emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, - QObject::tr("Test run canceled by user."))); + emitTestResultCreated(new FaultyTestResult(Result::MESSAGE_FATAL, + QObject::tr("Test run canceled by user."))); } qApp->processEvents(); } @@ -188,7 +188,7 @@ void performTestRun(QFutureInterface &futureInterface, if (testProcess.state() != QProcess::NotRunning) { testProcess.kill(); testProcess.waitForFinished(); - emitTestResultCreated(FaultyTestResult(Result::MESSAGE_FATAL, QObject::tr( + emitTestResultCreated(new FaultyTestResult(Result::MESSAGE_FATAL, QObject::tr( "Test case canceled due to timeout. \nMaybe raise the timeout?"))); } } @@ -208,14 +208,14 @@ void TestRunner::prepareToRunTests() foreach (TestConfiguration *config, m_selectedTests) { if (!omitRunConfigWarnings && config->guessedConfiguration()) { - TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, + TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MESSAGE_WARN, tr("Project's run configuration was guessed for \"%1\".\n" "This might cause trouble during execution.").arg(config->displayName()))); } } if (m_selectedTests.empty()) { - TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, + TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MESSAGE_WARN, tr("No tests selected. Canceling test run."))); onFinished(); return; @@ -223,7 +223,7 @@ void TestRunner::prepareToRunTests() ProjectExplorer::Project *project = m_selectedTests.at(0)->project(); if (!project) { - TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_WARN, + TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MESSAGE_WARN, tr("Project is null. Canceling test run.\n" "Only desktop kits are supported. Make sure the " "currently active kit is a desktop kit."))); @@ -239,7 +239,7 @@ void TestRunner::prepareToRunTests() if (project->hasActiveBuildSettings()) { buildProject(project); } else { - TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_FATAL, + TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MESSAGE_FATAL, tr("Project is not configured. Canceling test run."))); onFinished(); return; @@ -284,7 +284,7 @@ void TestRunner::buildFinished(bool success) if (success) { runTests(); } else { - TestResultsPane::instance()->addTestResult(FaultyTestResult(Result::MESSAGE_FATAL, + TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MESSAGE_FATAL, tr("Build failed. Canceling test run."))); onFinished(); } diff --git a/plugins/autotest/testrunner.h b/plugins/autotest/testrunner.h index 92de02f67b9..e03a0c3d4d5 100644 --- a/plugins/autotest/testrunner.h +++ b/plugins/autotest/testrunner.h @@ -47,7 +47,7 @@ public: signals: void testRunStarted(); void testRunFinished(); - void testResultCreated(const TestResult &testResult); + void testResultCreated(TestResult *testResult); void requestStopTestRun(); public slots: diff --git a/plugins/autotest/testxmloutputreader.cpp b/plugins/autotest/testxmloutputreader.cpp index ae6c223f933..f137b8d1d6e 100644 --- a/plugins/autotest/testxmloutputreader.cpp +++ b/plugins/autotest/testxmloutputreader.cpp @@ -208,8 +208,12 @@ void TestXmlOutputReader::processOutput() while (m_testApplication->canReadLine()) { // TODO Qt5 uses UTF-8 - while Qt4 uses ISO-8859-1 - could this be a problem? const QString line = QString::fromUtf8(m_testApplication->readLine()).trimmed(); - if (line.isEmpty() || xmlStartsWith(line, QLatin1String(""))) { - TestResult testResult(className, testCase, dataTag, result, description); + TestResult *testResult = new TestResult(className, testCase, dataTag, result, description); if (!file.isEmpty()) file = constructSourceFilePath(m_testApplication->workingDirectory(), file, m_testApplication->program()); - testResult.setFileName(file); - testResult.setLine(lineNumber); + testResult->setFileName(file); + testResult->setLine(lineNumber); testResultCreated(testResult); } continue; } if (xmlExtractBenchmarkInformation(line, QLatin1String("") || line == QLatin1String("")) { - TestResult testResult(className, testCase, dataTag, result, description); + TestResult *testResult = new TestResult(className, testCase, dataTag, result, description); if (!file.isEmpty()) file = constructSourceFilePath(m_testApplication->workingDirectory(), file, m_testApplication->program()); - testResult.setFileName(file); - testResult.setLine(lineNumber); + testResult->setFileName(file); + testResult->setLine(lineNumber); testResultCreated(testResult); description = QString(); } else if (line == QLatin1String("") && !duration.isEmpty()) { - TestResult testResult(className, testCase, QString(), Result::MESSAGE_INTERNAL, - QObject::tr("Execution took %1 ms.").arg(duration)); - testResultCreated(testResult); + testResultCreated(new TestResult(className, testCase, QString(), Result::MESSAGE_INTERNAL, + QObject::tr("Execution took %1 ms.").arg(duration))); emit increaseProgress(); } else if (line == QLatin1String("") && !duration.isEmpty()) { - TestResult testResult(className, QString(), QString(), Result::MESSAGE_INTERNAL, - QObject::tr("Test execution took %1 ms.").arg(duration)); - testResultCreated(testResult); + testResultCreated(new TestResult(className, QString(), QString(), Result::MESSAGE_TEST_CASE_END, + QObject::tr("Test execution took %1 ms.").arg(duration))); } else if (readingDescription) { if (line.endsWith(QLatin1String("]]>"))) { description.append(QLatin1Char('\n')); @@ -283,10 +285,10 @@ void TestXmlOutputReader::processOutput() description.append(line); } } else if (xmlStartsWith(line, QLatin1String(""), qtVersion)) { - testResultCreated(FaultyTestResult(Result::MESSAGE_INTERNAL, + testResultCreated(new TestResult(className, QString(), QString(), Result::MESSAGE_INTERNAL, QObject::tr("Qt version: %1").arg(qtVersion))); } else if (xmlStartsWith(line, QLatin1String(""), qtestVersion)) { - testResultCreated(FaultyTestResult(Result::MESSAGE_INTERNAL, + testResultCreated(new TestResult(className, QString(), QString(), Result::MESSAGE_INTERNAL, QObject::tr("QTest version: %1").arg(qtestVersion))); } else { // qDebug() << "Unhandled line:" << line; // TODO remove diff --git a/plugins/autotest/testxmloutputreader.h b/plugins/autotest/testxmloutputreader.h index 1ca22b96989..6dfcef51ccc 100644 --- a/plugins/autotest/testxmloutputreader.h +++ b/plugins/autotest/testxmloutputreader.h @@ -45,7 +45,7 @@ public: public slots: void processOutput(); signals: - void testResultCreated(const TestResult &testResult); + void testResultCreated(TestResult *testResult); void increaseProgress(); private: QProcess *m_testApplication; From 0d01a0c7bfe2c80700b64e1b56c1172cc99a6f45 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 4 Sep 2015 10:57:05 +0200 Subject: [PATCH 140/200] Simplify check state handling Data functions and special functions cannot be checked at all, so there is no need to inherit the state by its parent. Change-Id: If72f79ef6bcd77628916bd7fbe137faa5555db41 Reviewed-by: Niels Weber Reviewed-by: David Schulz --- plugins/autotest/testtreeitem.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index 721c605473e..5119f4a206d 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -30,21 +30,10 @@ TestTreeItem::TestTreeItem(const QString &name, const QString &filePath, Type ty m_parent(parent) { switch (m_type) { - case ROOT: - m_checked = Qt::Unchecked; - break; case TEST_CLASS: case TEST_FUNCTION: m_checked = Qt::Checked; break; - case TEST_DATAFUNCTION: - case TEST_SPECIALFUNCTION: - if (m_parent) - m_checked = m_parent->checked() == Qt::PartiallyChecked ? Qt::Unchecked - : m_parent->checked(); - else - m_checked = Qt::Unchecked; - break; default: m_checked = Qt::Unchecked; } @@ -169,7 +158,7 @@ Qt::CheckState TestTreeItem::checked() const return m_checked; case TEST_DATAFUNCTION: case TEST_SPECIALFUNCTION: - return m_parent->m_checked == Qt::PartiallyChecked ? Qt::Unchecked : m_parent->m_checked; + return Qt::Unchecked; default: if (m_parent) return m_parent->m_checked; From b4dcfc1d91872fae64466da8b38bdcb9e1fad855 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 4 Sep 2015 11:02:14 +0200 Subject: [PATCH 141/200] Let TestTreeItem handle its parent Part of preparing to re-use QC's TreeModel/TreeItem for TestTreeModel/TestTreeItem. Change-Id: Ieab26e9061790dd4c3d8dc64ce292727a17977f7 Reviewed-by: Niels Weber Reviewed-by: David Schulz --- plugins/autotest/testcodeparser.cpp | 4 ++-- plugins/autotest/testtreeitem.cpp | 18 ++++++++++-------- plugins/autotest/testtreeitem.h | 3 +-- plugins/autotest/testtreemodel.cpp | 12 ++++-------- 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index b7a13b4ee84..e0a5ea3226d 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -398,7 +398,7 @@ static TestTreeItem constructTestTreeItem(const QString &fileName, foreach (const QString &functionName, functions.keys()) { const TestCodeLocationAndType locationAndType = functions.value(functionName); TestTreeItem *treeItemChild = new TestTreeItem(functionName, locationAndType.m_name, - locationAndType.m_type, &treeItem); + locationAndType.m_type); treeItemChild->setLine(locationAndType.m_line); treeItemChild->setColumn(locationAndType.m_column); // check for data tags and if there are any for this function add them @@ -408,7 +408,7 @@ static TestTreeItem constructTestTreeItem(const QString &fileName, foreach (const TestCodeLocationAndType &tagLocation, tags) { TestTreeItem *tagTreeItem = new TestTreeItem(tagLocation.m_name, locationAndType.m_name, - tagLocation.m_type, treeItemChild); + tagLocation.m_type); tagTreeItem->setLine(tagLocation.m_line); tagTreeItem->setColumn(tagLocation.m_column); treeItemChild->appendChild(tagTreeItem); diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index 5119f4a206d..78d91c4490c 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -19,15 +19,17 @@ #include "testtreeitem.h" +#include + namespace Autotest { namespace Internal { -TestTreeItem::TestTreeItem(const QString &name, const QString &filePath, Type type, TestTreeItem *parent) +TestTreeItem::TestTreeItem(const QString &name, const QString &filePath, Type type) : m_name(name), m_filePath(filePath), m_type(type), m_line(0), - m_parent(parent) + m_parent(0) { switch (m_type) { case TEST_CLASS: @@ -52,13 +54,10 @@ TestTreeItem::TestTreeItem(const TestTreeItem &other) m_line(other.m_line), m_column(other.m_column), m_mainFile(other.m_mainFile), - m_parent(other.m_parent) + m_parent(0) { - foreach (const TestTreeItem *child, other.m_children) { - TestTreeItem *reparentedChild = new TestTreeItem(*child); - reparentedChild->m_parent = this; - m_children.append(reparentedChild); - } + foreach (const TestTreeItem *child, other.m_children) + appendChild(new TestTreeItem(*child)); } TestTreeItem *TestTreeItem::child(int row) const @@ -73,6 +72,9 @@ TestTreeItem *TestTreeItem::parent() const void TestTreeItem::appendChild(TestTreeItem *child) { + QTC_ASSERT(child->m_parent == 0, return); + + child->m_parent = this; m_children.append(child); } diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index 8c7bf14307f..0d25350eda0 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -41,7 +41,7 @@ public: }; TestTreeItem(const QString &name = QString(), const QString &filePath = QString(), - Type type = ROOT, TestTreeItem *parent = 0); + Type type = ROOT); virtual ~TestTreeItem(); TestTreeItem(const TestTreeItem& other); @@ -67,7 +67,6 @@ public: void setChecked(const Qt::CheckState checked); Qt::CheckState checked() const; Type type() const { return m_type; } - void setParent(TestTreeItem *parent) { m_parent = parent; } QList getChildNames() const; private: diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 0b43688982c..9f0cf75a275 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -41,8 +41,8 @@ namespace Internal { TestTreeModel::TestTreeModel(QObject *parent) : QAbstractItemModel(parent), m_rootItem(new TestTreeItem(QString(), QString(), TestTreeItem::ROOT)), - m_autoTestRootItem(new TestTreeItem(tr("Auto Tests"), QString(), TestTreeItem::ROOT, m_rootItem)), - m_quickTestRootItem(new TestTreeItem(tr("Qt Quick Tests"), QString(), TestTreeItem::ROOT, m_rootItem)), + m_autoTestRootItem(new TestTreeItem(tr("Auto Tests"), QString(), TestTreeItem::ROOT)), + m_quickTestRootItem(new TestTreeItem(tr("Qt Quick Tests"), QString(), TestTreeItem::ROOT)), m_parser(new TestCodeParser(this)), m_connectionsInitialized(false) { @@ -664,7 +664,6 @@ void TestTreeModel::addTestTreeItem(const TestTreeItem &item, TestTreeModel::Typ TestTreeItem *parent = rootItemForType(type); QModelIndex index = rootIndexForType(type); TestTreeItem *toBeAdded = new TestTreeItem(item); - toBeAdded->setParent(parent); beginInsertRows(index, parent->childCount(), parent->childCount()); parent->appendChild(toBeAdded); @@ -680,7 +679,6 @@ void TestTreeModel::addTestTreeItems(const QList &itemList, TestTr beginInsertRows(index, parent->childCount(), parent->childCount() + itemList.size() - 1); foreach (const TestTreeItem &item, itemList) { TestTreeItem *toBeAdded = new TestTreeItem(item); - toBeAdded->setParent(parent); parent->appendChild(toBeAdded); } endInsertRows(); @@ -693,12 +691,12 @@ void TestTreeModel::updateUnnamedQuickTest(const QString &fileName, const QStrin removeUnnamedQuickTests(fileName); TestTreeItem unnamed = hasUnnamedQuickTests() ? TestTreeItem(*unnamedQuickTests()) - : TestTreeItem(QString(), QString(), TestTreeItem::TEST_CLASS, rootItemForType(QuickTest)); + : TestTreeItem(QString(), QString(), TestTreeItem::TEST_CLASS); foreach (const QString &functionName, functions.keys()) { const TestCodeLocationAndType locationAndType = functions.value(functionName); TestTreeItem *testFunction = new TestTreeItem(functionName, locationAndType.m_name, - locationAndType.m_type, &unnamed); + locationAndType.m_type); testFunction->setLine(locationAndType.m_line); testFunction->setColumn(locationAndType.m_column); testFunction->setMainFile(mainFile); @@ -714,7 +712,6 @@ void TestTreeModel::modifyTestTreeItem(TestTreeItem item, TestTreeModel::Type ty { QModelIndex index = rootIndexForType(type); TestTreeItem *parent = rootItemForType(type); - item.setParent(parent); if (file.isEmpty()) { if (TestTreeItem *unnamed = unnamedQuickTests()) { index = index.child(unnamed->row(), 0); @@ -805,7 +802,6 @@ void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, const Test for (int row = childCount; row < newChildCount; ++row) { TestTreeItem *newChild = newItem.child(row); TestTreeItem *toBeAdded = new TestTreeItem(*newChild); - toBeAdded->setParent(toBeModifiedItem); if (checkStates.contains(toBeAdded->name()) && checkStates.value(toBeAdded->name()) != Qt::Checked) toBeAdded->setChecked(checkStates.value(toBeAdded->name())); From 8f00ae98e69dd0f7df5e04fb34643bdcd8135784 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 7 Sep 2015 14:44:45 +0200 Subject: [PATCH 142/200] Use pointers for test tree items Part of preparing to re-use QC's TreeModel/TreeItem for TestTreeModel/TestTreeItem. Change-Id: I8699405c3dcad88df67171af2d542bc8e3fd2fc0 Reviewed-by: David Schulz --- plugins/autotest/autotestplugin.cpp | 2 +- plugins/autotest/testcodeparser.cpp | 67 ++++++++++++++--------------- plugins/autotest/testcodeparser.h | 10 ++--- plugins/autotest/testtreeitem.h | 2 +- plugins/autotest/testtreemodel.cpp | 52 ++++++++++++---------- plugins/autotest/testtreemodel.h | 10 ++--- 6 files changed, 74 insertions(+), 69 deletions(-) diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index 9c32e0b75c2..c024aa2bd25 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -63,7 +63,7 @@ AutotestPlugin::AutotestPlugin() { // needed to be used in QueuedConnection connects qRegisterMetaType(); - qRegisterMetaType(); + qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index e0a5ea3226d..b5451aef8eb 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -382,18 +382,17 @@ static QMap checkForDataTags(const QString &fileN return QMap(); } - -static TestTreeItem constructTestTreeItem(const QString &fileName, - const QString &mainFile, // used for Quick Tests only - const QString &testCaseName, - int line, int column, - const QMap functions, - const QMap dataTags = QMap()) +static TestTreeItem *constructTestTreeItem(const QString &fileName, + const QString &mainFile, // used for Quick Tests only + const QString &testCaseName, + int line, int column, + const QMap &functions, + const QMap dataTags = QMap()) { - TestTreeItem treeItem(testCaseName, fileName, TestTreeItem::TEST_CLASS); - treeItem.setMainFile(mainFile); // used for Quick Tests only - treeItem.setLine(line); - treeItem.setColumn(column); + TestTreeItem *treeItem = new TestTreeItem(testCaseName, fileName, TestTreeItem::TEST_CLASS); + treeItem->setMainFile(mainFile); // used for Quick Tests only + treeItem->setLine(line); + treeItem->setColumn(column); foreach (const QString &functionName, functions.keys()) { const TestCodeLocationAndType locationAndType = functions.value(functionName); @@ -401,6 +400,7 @@ static TestTreeItem constructTestTreeItem(const QString &fileName, locationAndType.m_type); treeItemChild->setLine(locationAndType.m_line); treeItemChild->setColumn(locationAndType.m_column); + // check for data tags and if there are any for this function add them const QString qualifiedFunctionName = testCaseName + QLatin1String("::") + functionName; if (dataTags.contains(qualifiedFunctionName)) { @@ -415,7 +415,7 @@ static TestTreeItem constructTestTreeItem(const QString &fileName, } } - treeItem.appendChild(treeItemChild); + treeItem->appendChild(treeItemChild); } return treeItem; } @@ -482,9 +482,10 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr document) const QMap dataTags = checkForDataTags(declaringDoc->fileName(), testFunctions); - TestTreeItem item = constructTestTreeItem(declaringDoc->fileName(), QString(), - testCaseName, line, column, testFunctions, - dataTags); + TestTreeItem *item = constructTestTreeItem(declaringDoc->fileName(), QString(), + testCaseName, line, column, testFunctions, + dataTags); + updateModelAndCppDocMap(document, declaringDoc->fileName(), item); return; } @@ -532,7 +533,7 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr document) } // end of handling test cases without name property // construct new/modified TestTreeItem - TestTreeItem testTreeItem + TestTreeItem *testTreeItem = constructTestTreeItem(tcLocationAndType.m_name, cppFileName, testCaseName, tcLocationAndType.m_line, tcLocationAndType.m_column, testFunctions); @@ -761,14 +762,11 @@ void TestCodeParser::removeTestsIfNecessary(const QString &fileName) // unnamed Quick Tests must be handled separately if (fileName.endsWith(QLatin1String(".qml"))) { removeUnnamedQuickTestsByName(fileName); - emit unnamedQuickTestsRemoved(fileName); } else { QSet filePaths; m_model->qmlFilesForMainFile(fileName, &filePaths); - foreach (const QString &file, filePaths) { + foreach (const QString &file, filePaths) removeUnnamedQuickTestsByName(file); - emit unnamedQuickTestsRemoved(file); - } } } } @@ -862,37 +860,37 @@ void TestCodeParser::updateUnnamedQuickTests(const QString &fileName, const QStr m_unnamedQuickDocList.append(info); } - emit unnamedQuickTestsUpdated(fileName, mainFile, functions); + emit unnamedQuickTestsUpdated(mainFile, functions); } void TestCodeParser::updateModelAndCppDocMap(CPlusPlus::Document::Ptr document, - const QString &declaringFile, TestTreeItem &testItem) + const QString &declaringFile, TestTreeItem *testItem) { const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); const QString fileName = document->fileName(); - const QString testCaseName = testItem.name(); + const QString testCaseName = testItem->name(); QString proFile; const QList ppList = cppMM->projectPart(fileName); if (ppList.size()) proFile = ppList.at(0)->projectFile; if (m_cppDocMap.contains(fileName)) { - QStringList files = QStringList() << fileName; + QStringList files = { fileName }; if (fileName != declaringFile) files << declaringFile; foreach (const QString &file, files) { const bool setReferencingFile = (files.size() == 2 && file == declaringFile); - emit testItemModified(testItem, TestTreeModel::AutoTest, file); - TestInfo testInfo(testCaseName, testItem.getChildNames(), + TestInfo testInfo(testCaseName, testItem->getChildNames(), document->revision(), document->editorRevision()); testInfo.setProfile(proFile); if (setReferencingFile) testInfo.setReferencingFile(fileName); m_cppDocMap.insert(file, testInfo); } + emit testItemModified(testItem, TestTreeModel::AutoTest, files); } else { emit testItemCreated(testItem, TestTreeModel::AutoTest); - TestInfo ti(testCaseName, testItem.getChildNames(), + TestInfo ti(testCaseName, testItem->getChildNames(), document->revision(), document->editorRevision()); ti.setProfile(proFile); m_cppDocMap.insert(fileName, ti); @@ -905,7 +903,7 @@ void TestCodeParser::updateModelAndCppDocMap(CPlusPlus::Document::Ptr document, void TestCodeParser::updateModelAndQuickDocMap(QmlJS::Document::Ptr document, const QString &referencingFile, - TestTreeItem &testItem) + TestTreeItem *testItem) { const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); const QString fileName = document->fileName(); @@ -915,21 +913,21 @@ void TestCodeParser::updateModelAndQuickDocMap(QmlJS::Document::Ptr document, proFile = ppList.at(0)->projectFile; if (m_quickDocMap.contains(fileName)) { - emit testItemModified(testItem, TestTreeModel::QuickTest, fileName); - TestInfo testInfo(testItem.name(), testItem.getChildNames(), 0, document->editorRevision()); + TestInfo testInfo(testItem->name(), testItem->getChildNames(), 0, document->editorRevision()); testInfo.setReferencingFile(referencingFile); testInfo.setProfile(proFile); + emit testItemModified(testItem, TestTreeModel::QuickTest, { fileName }); m_quickDocMap.insert(fileName, testInfo); } else { // if it was formerly unnamed remove the respective items removeUnnamedQuickTestsByName(fileName); - emit unnamedQuickTestsRemoved(fileName); - emit testItemCreated(testItem, TestTreeModel::QuickTest); - TestInfo testInfo(testItem.name(), testItem.getChildNames(), 0, document->editorRevision()); + const QString &filePath = testItem->filePath(); + TestInfo testInfo(testItem->name(), testItem->getChildNames(), 0, document->editorRevision()); testInfo.setReferencingFile(referencingFile); testInfo.setProfile(proFile); - m_quickDocMap.insert(testItem.filePath(), testInfo); + emit testItemCreated(testItem, TestTreeModel::QuickTest); + m_quickDocMap.insert(filePath, testInfo); } } @@ -939,6 +937,7 @@ void TestCodeParser::removeUnnamedQuickTestsByName(const QString &fileName) if (m_unnamedQuickDocList.at(i).fileName() == fileName) m_unnamedQuickDocList.removeAt(i); } + emit unnamedQuickTestsRemoved(fileName); } #ifdef WITH_TESTS diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 5bb54d93203..0ba16ff7621 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -66,11 +66,11 @@ public: signals: void cacheCleared(); - void testItemCreated(const TestTreeItem &item, TestTreeModel::Type type); + void testItemCreated(TestTreeItem *item, TestTreeModel::Type type); void testItemsCreated(const QList &itemList, TestTreeModel::Type type); - void testItemModified(TestTreeItem tItem, TestTreeModel::Type type, const QString &file); + void testItemModified(TestTreeItem *tItem, TestTreeModel::Type type, const QStringList &file); void testItemsRemoved(const QString &filePath, TestTreeModel::Type type); - void unnamedQuickTestsUpdated(const QString &filePath, const QString &mainFile, + void unnamedQuickTestsUpdated(const QString &mainFile, const QMap &functions); void unnamedQuickTestsRemoved(const QString &filePath); void parsingStarted(); @@ -103,9 +103,9 @@ private: void updateUnnamedQuickTests(const QString &fileName, const QString &mainFile, const QMap &functions); void updateModelAndCppDocMap(CPlusPlus::Document::Ptr document, - const QString &declaringFile, TestTreeItem &testItem); + const QString &declaringFile, TestTreeItem *testItem); void updateModelAndQuickDocMap(QmlJS::Document::Ptr document, - const QString &referencingFile, TestTreeItem &testItem); + const QString &referencingFile, TestTreeItem *testItem); void removeUnnamedQuickTestsByName(const QString &fileName); TestTreeModel *m_model; diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index 0d25350eda0..79bb7e6c188 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -95,7 +95,7 @@ typedef QVector TestCodeLocationList; } // namespace Internal } // namespace Autotest -Q_DECLARE_METATYPE(Autotest::Internal::TestTreeItem) +Q_DECLARE_METATYPE(Autotest::Internal::TestTreeItem *) Q_DECLARE_METATYPE(Autotest::Internal::TestCodeLocationAndType) #endif // TESTTREEITEM_H diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 9f0cf75a275..b6b9c8ca3a3 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -659,14 +659,13 @@ void TestTreeModel::removeUnnamedQuickTests(const QString &filePath) emit testTreeModelChanged(); } -void TestTreeModel::addTestTreeItem(const TestTreeItem &item, TestTreeModel::Type type) +void TestTreeModel::addTestTreeItem(TestTreeItem *item, TestTreeModel::Type type) { TestTreeItem *parent = rootItemForType(type); QModelIndex index = rootIndexForType(type); - TestTreeItem *toBeAdded = new TestTreeItem(item); beginInsertRows(index, parent->childCount(), parent->childCount()); - parent->appendChild(toBeAdded); + parent->appendChild(item); endInsertRows(); emit testTreeModelChanged(); } @@ -682,17 +681,21 @@ void TestTreeModel::addTestTreeItems(const QList &itemList, TestTr parent->appendChild(toBeAdded); } endInsertRows(); - emit testTreeModelChanged(); } -void TestTreeModel::updateUnnamedQuickTest(const QString &fileName, const QString &mainFile, +void TestTreeModel::updateUnnamedQuickTest(const QString &mainFile, const QMap &functions) { - removeUnnamedQuickTests(fileName); - TestTreeItem unnamed = hasUnnamedQuickTests() - ? TestTreeItem(*unnamedQuickTests()) - : TestTreeItem(QString(), QString(), TestTreeItem::TEST_CLASS); + if (functions.isEmpty()) + return; + if (!hasUnnamedQuickTests()) + addTestTreeItem(new TestTreeItem(QString(), QString(), TestTreeItem::TEST_CLASS), QuickTest); + + TestTreeItem *unnamed = unnamedQuickTests(); + QModelIndex unnamedIndex = index(unnamed->row(), 0, rootIndexForType(QuickTest)); + + beginInsertRows(unnamedIndex, unnamed->childCount(), unnamed->childCount() + functions.size()); foreach (const QString &functionName, functions.keys()) { const TestCodeLocationAndType locationAndType = functions.value(functionName); TestTreeItem *testFunction = new TestTreeItem(functionName, locationAndType.m_name, @@ -700,32 +703,35 @@ void TestTreeModel::updateUnnamedQuickTest(const QString &fileName, const QStrin testFunction->setLine(locationAndType.m_line); testFunction->setColumn(locationAndType.m_column); testFunction->setMainFile(mainFile); - unnamed.appendChild(testFunction); + unnamed->appendChild(testFunction); } - if (hasUnnamedQuickTests()) - modifyTestTreeItem(unnamed, QuickTest, QString()); - else - addTestTreeItem(unnamed, QuickTest); + endInsertRows(); } -void TestTreeModel::modifyTestTreeItem(TestTreeItem item, TestTreeModel::Type type, const QString &file) +void TestTreeModel::modifyTestTreeItem(TestTreeItem *item, TestTreeModel::Type type, const QStringList &files) { QModelIndex index = rootIndexForType(type); TestTreeItem *parent = rootItemForType(type); - if (file.isEmpty()) { + if (files.isEmpty()) { if (TestTreeItem *unnamed = unnamedQuickTests()) { + if (unnamed == item) // no need to update or delete + return; + index = index.child(unnamed->row(), 0); modifyTestSubtree(index, item); } } else { for (int row = 0; row < parent->childCount(); ++row) { - if (parent->child(row)->filePath() == file) { + if (files.contains(parent->child(row)->filePath())) { index = index.child(row, 0); modifyTestSubtree(index, item); break; } } } + // item was created as temporary, destroy it if it won't get destroyed by its parent + if (!item->parent()) + delete item; } void TestTreeModel::removeAllTestItems() @@ -774,19 +780,19 @@ QModelIndex TestTreeModel::rootIndexForType(TestTreeModel::Type type) QTC_ASSERT(false, return QModelIndex()); } -void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, const TestTreeItem &newItem) +void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, const TestTreeItem *newItem) { if (!toBeModifiedIndex.isValid()) return; TestTreeItem *toBeModifiedItem = static_cast(toBeModifiedIndex.internalPointer()); - if (toBeModifiedItem->modifyContent(&newItem)) + if (toBeModifiedItem->modifyContent(newItem)) emit dataChanged(toBeModifiedIndex, toBeModifiedIndex, QVector() << Qt::DisplayRole << Qt::ToolTipRole << LinkRole); // process sub-items as well... const int childCount = toBeModifiedItem->childCount(); - const int newChildCount = newItem.childCount(); + const int newChildCount = newItem->childCount(); // for keeping the CheckState on modifications // TODO might still fail for duplicate entries @@ -800,7 +806,7 @@ void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, const Test processChildren(toBeModifiedIndex, newItem, childCount, checkStates); // add additional items for (int row = childCount; row < newChildCount; ++row) { - TestTreeItem *newChild = newItem.child(row); + TestTreeItem *newChild = newItem->child(row); TestTreeItem *toBeAdded = new TestTreeItem(*newChild); if (checkStates.contains(toBeAdded->name()) && checkStates.value(toBeAdded->name()) != Qt::Checked) @@ -817,7 +823,7 @@ void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, const Test emit testTreeModelChanged(); } -void TestTreeModel::processChildren(QModelIndex &parentIndex, const TestTreeItem &newItem, +void TestTreeModel::processChildren(QModelIndex &parentIndex, const TestTreeItem *newItem, const int upperBound, const QHash &checkStates) { @@ -827,7 +833,7 @@ void TestTreeModel::processChildren(QModelIndex &parentIndex, const TestTreeItem for (int row = 0; row < upperBound; ++row) { QModelIndex child = parentIndex.child(row, 0); TestTreeItem *toBeModifiedChild = toBeModifiedItem->child(row); - TestTreeItem *modifiedChild = newItem.child(row); + TestTreeItem *modifiedChild = newItem->child(row); if (toBeModifiedChild->modifyContent(modifiedChild)) emit dataChanged(child, child, modificationRoles); diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 785606c36a8..003336e5b87 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -91,11 +91,11 @@ signals: public slots: private: - void addTestTreeItem(const TestTreeItem &item, Type type); + void addTestTreeItem(TestTreeItem *item, Type type); void addTestTreeItems(const QList &itemList, Type type); - void updateUnnamedQuickTest(const QString &fileName, const QString &mainFile, + void updateUnnamedQuickTest(const QString &mainFile, const QMap &functions); - void modifyTestTreeItem(TestTreeItem item, Type type, const QString &file); + void modifyTestTreeItem(TestTreeItem *item, Type type, const QStringList &file); void removeAllTestItems(); void removeTestTreeItems(const QString &filePath, Type type); void removeUnnamedQuickTests(const QString &filePath); @@ -105,8 +105,8 @@ private: QModelIndex rootIndexForType(Type type); explicit TestTreeModel(QObject *parent = 0); - void modifyTestSubtree(QModelIndex &toBeModifiedIndex, const TestTreeItem &newItem); - void processChildren(QModelIndex &parentIndex, const TestTreeItem &newItem, + void modifyTestSubtree(QModelIndex &toBeModifiedIndex, const TestTreeItem *newItem); + void processChildren(QModelIndex &parentIndex, const TestTreeItem *newItem, const int upperBound, const QHash &checkStates); TestTreeItem *m_rootItem; From 93e741270b3ab198dea78ec748fe83eaebc41843 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 8 Sep 2015 09:11:50 +0200 Subject: [PATCH 143/200] Remove unused code Change-Id: I5a5f41222a572f1ae3662e5c48c72b4a6adfbc13 Reviewed-by: Niels Weber Reviewed-by: David Schulz --- plugins/autotest/testcodeparser.h | 1 - plugins/autotest/testtreemodel.cpp | 15 --------------- plugins/autotest/testtreemodel.h | 1 - 3 files changed, 17 deletions(-) diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 0ba16ff7621..3c5529f63a6 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -67,7 +67,6 @@ public: signals: void cacheCleared(); void testItemCreated(TestTreeItem *item, TestTreeModel::Type type); - void testItemsCreated(const QList &itemList, TestTreeModel::Type type); void testItemModified(TestTreeItem *tItem, TestTreeModel::Type type, const QStringList &file); void testItemsRemoved(const QString &filePath, TestTreeModel::Type type); void unnamedQuickTestsUpdated(const QString &mainFile, diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index b6b9c8ca3a3..ccc7616df45 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -53,8 +53,6 @@ TestTreeModel::TestTreeModel(QObject *parent) : &TestTreeModel::removeAllTestItems, Qt::QueuedConnection); connect(m_parser, &TestCodeParser::testItemCreated, this, &TestTreeModel::addTestTreeItem, Qt::QueuedConnection); - connect(m_parser, &TestCodeParser::testItemsCreated, - this, &TestTreeModel::addTestTreeItems, Qt::QueuedConnection); connect(m_parser, &TestCodeParser::testItemModified, this, &TestTreeModel::modifyTestTreeItem, Qt::QueuedConnection); connect(m_parser, &TestCodeParser::testItemsRemoved, @@ -670,19 +668,6 @@ void TestTreeModel::addTestTreeItem(TestTreeItem *item, TestTreeModel::Type type emit testTreeModelChanged(); } -void TestTreeModel::addTestTreeItems(const QList &itemList, TestTreeModel::Type type) -{ - TestTreeItem *parent = rootItemForType(type); - QModelIndex index = rootIndexForType(type); - - beginInsertRows(index, parent->childCount(), parent->childCount() + itemList.size() - 1); - foreach (const TestTreeItem &item, itemList) { - TestTreeItem *toBeAdded = new TestTreeItem(item); - parent->appendChild(toBeAdded); - } - endInsertRows(); -} - void TestTreeModel::updateUnnamedQuickTest(const QString &mainFile, const QMap &functions) { diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 003336e5b87..7a7deaeb135 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -92,7 +92,6 @@ public slots: private: void addTestTreeItem(TestTreeItem *item, Type type); - void addTestTreeItems(const QList &itemList, Type type); void updateUnnamedQuickTest(const QString &mainFile, const QMap &functions); void modifyTestTreeItem(TestTreeItem *item, Type type, const QStringList &file); From 65d3a27db70e5122641b37c5e8649122c6937a94 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 1 Oct 2015 09:10:49 +0200 Subject: [PATCH 144/200] Fix keyboard handling on results pane Change-Id: Ib9a8d600af122bf0d6ed2cc7a63badc90fb88d43 Reviewed-by: David Schulz --- plugins/autotest/testresultspane.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index c971321333c..abc91dfb66e 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -58,6 +58,7 @@ void ResultsTreeView::keyPressEvent(QKeyEvent *event) emit copyShortcutTriggered(); event->accept(); } + TreeView::keyPressEvent(event); } TestResultsPane::TestResultsPane(QObject *parent) : From 475d6b3af29a1e84baf23021aa7a68e8c0b49c13 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 10 Sep 2015 10:57:15 +0200 Subject: [PATCH 145/200] Move data handling almost from model to item Part of preparing to re-use QC's TreeModel/TreeItem for TestTreeModel/TestTreeItem. Change-Id: I3752d800d836a5cd9067cacfcd181d93ec957095 Reviewed-by: David Schulz --- plugins/autotest/testtreeitem.cpp | 85 ++++++++++++++++++ plugins/autotest/testtreeitem.h | 14 +++ plugins/autotest/testtreeitemdelegate.cpp | 1 + plugins/autotest/testtreemodel.cpp | 101 ++-------------------- plugins/autotest/testtreemodel.h | 9 -- 5 files changed, 108 insertions(+), 102 deletions(-) diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index 78d91c4490c..bea7766287b 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -17,10 +17,16 @@ ** ****************************************************************************/ +#include "autotestconstants.h" #include "testtreeitem.h" #include +#include +#include + +#include + namespace Autotest { namespace Internal { @@ -78,6 +84,85 @@ void TestTreeItem::appendChild(TestTreeItem *child) m_children.append(child); } +static QIcon testTreeIcon(TestTreeItem::Type type) +{ + static QIcon icons[] = { + QIcon(), + QIcon(QLatin1String(":/images/class.png")), + QIcon(QLatin1String(":/images/func.png")), + QIcon(QLatin1String(":/images/data.png")) + }; + if (type >= sizeof(icons)) + return icons[2]; + return icons[type]; +} + +QVariant TestTreeItem::data(int /*column*/, int role) const +{ + switch (role) { + case Qt::DisplayRole: + if (m_type == ROOT && childCount() == 0) + return QString(m_name + QObject::tr(" (none)")); + else if (m_name.isEmpty()) + return QObject::tr(Constants::UNNAMED_QUICKTESTS); + else + return m_name; + case Qt::ToolTipRole: + if (m_type == TEST_CLASS && m_name.isEmpty()) { + return QObject::tr("

Give all test cases a name to ensure correct behavior " + "when running test cases and to be able to select them.

"); + } + return m_filePath; + case Qt::DecorationRole: + return testTreeIcon(m_type); + case Qt::CheckStateRole: + switch (m_type) { + case ROOT: + case TEST_DATAFUNCTION: + case TEST_SPECIALFUNCTION: + return QVariant(); + case TEST_CLASS: + return m_name.isEmpty() ? QVariant() : checked(); + case TEST_FUNCTION: + if (m_parent && m_parent->name().isEmpty()) + return QVariant(); + return checked(); + default: + return checked(); + } + case LinkRole: { + QVariant itemLink; + itemLink.setValue(TextEditor::TextEditorWidget::Link(m_filePath, m_line, m_column)); + return itemLink; + } + case ItalicRole: + switch (m_type) { + case TEST_DATAFUNCTION: + case TEST_SPECIALFUNCTION: + return true; + case TEST_CLASS: + return m_name.isEmpty(); + case TEST_FUNCTION: + return m_parent ? m_parent->name().isEmpty() : false; + default: + return false; + } + case TypeRole: + return m_type; + } + return QVariant(); +} + +bool TestTreeItem::setData(int /*column*/, const QVariant &data, int role) +{ + if (role == Qt::CheckStateRole) { + Qt::CheckState old = checked(); + setChecked((Qt::CheckState)data.toInt()); + return checked() != old; + } + return false; +} + int TestTreeItem::row() const { if (m_parent) diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index 79bb7e6c188..8a442e7f842 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -24,6 +24,18 @@ #include #include +QT_BEGIN_NAMESPACE +class QVariant; +QT_END_NAMESPACE + +namespace { + enum ItemRole { + LinkRole = Qt::UserRole + 2, // can be removed if AnnotationRole comes back + ItalicRole, // used only inside the delegate + TypeRole + }; +} + namespace Autotest { namespace Internal { @@ -48,6 +60,8 @@ public: TestTreeItem *child(int row) const; TestTreeItem *parent() const; void appendChild(TestTreeItem *child); + QVariant data(int column, int role) const; + bool setData(int column, const QVariant &data, int role); int row() const; int childCount() const; void removeChildren(); diff --git a/plugins/autotest/testtreeitemdelegate.cpp b/plugins/autotest/testtreeitemdelegate.cpp index 1e5952c7a02..7068c064724 100644 --- a/plugins/autotest/testtreeitemdelegate.cpp +++ b/plugins/autotest/testtreeitemdelegate.cpp @@ -17,6 +17,7 @@ ** ****************************************************************************/ +#include "testtreeitem.h" #include "testtreeitemdelegate.h" #include "testtreemodel.h" diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index ccc7616df45..e6ff3a2b74c 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -33,8 +33,6 @@ #include -#include - namespace Autotest { namespace Internal { @@ -176,19 +174,6 @@ int TestTreeModel::columnCount(const QModelIndex &) const return 1; } -static QIcon testTreeIcon(TestTreeItem::Type type) -{ - static QIcon icons[] = { - QIcon(), - QIcon(QLatin1String(":/images/class.png")), - QIcon(QLatin1String(":/images/func.png")), - QIcon(QLatin1String(":/images/data.png")) - }; - if (type >= sizeof(icons) / sizeof(icons[0])) - return icons[2]; - return icons[type]; -} - QVariant TestTreeModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) @@ -198,73 +183,7 @@ QVariant TestTreeModel::data(const QModelIndex &index, int role) const if (!item) return QVariant(); - if (role == Qt::DisplayRole) { - if ((item == m_autoTestRootItem && m_autoTestRootItem->childCount() == 0) - || (item == m_quickTestRootItem && m_quickTestRootItem->childCount() == 0)) { - return QString(item->name() + tr(" (none)")); - } else { - if (item->name().isEmpty() && item->type() == TestTreeItem::TEST_CLASS) - return tr(Constants::UNNAMED_QUICKTESTS); - return item->name(); - } - - return QVariant(); // TODO ? - } - switch(role) { - case Qt::ToolTipRole: - if (item->type() == TestTreeItem::TEST_CLASS && item->name().isEmpty()) - return tr("

Give all test cases a name to ensure correct behavior " - "when running test cases and to be able to select them.

"); - return item->filePath(); - case Qt::DecorationRole: - return testTreeIcon(item->type()); - case Qt::CheckStateRole: - switch (item->type()) { - case TestTreeItem::ROOT: - case TestTreeItem::TEST_DATATAG: - case TestTreeItem::TEST_DATAFUNCTION: - case TestTreeItem::TEST_SPECIALFUNCTION: - return QVariant(); - case TestTreeItem::TEST_CLASS: - if (item->name().isEmpty()) - return QVariant(); - else - return item->checked(); - case TestTreeItem::TEST_FUNCTION: - if (TestTreeItem *parent = item->parent()) - return parent->name().isEmpty() ? QVariant() : item->checked(); - else - return item->checked(); - default: - return item->checked(); - } - case LinkRole: { - QVariant itemLink; - TextEditor::TextEditorWidget::Link link(item->filePath(), item->line(), item->column()); - itemLink.setValue(link); - return itemLink; - } - case ItalicRole: - switch (item->type()) { - case TestTreeItem::TEST_DATAFUNCTION: - case TestTreeItem::TEST_SPECIALFUNCTION: - return true; - case TestTreeItem::TEST_CLASS: - return item->name().isEmpty(); - case TestTreeItem::TEST_FUNCTION: - if (TestTreeItem *parent = item->parent()) - return parent->name().isEmpty(); - else - return false; - default: - return false; - } - case TypeRole: - return item->type(); - } - - // TODO ? - return QVariant(); + return item->data(index.column(), role); } bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int role) @@ -272,27 +191,23 @@ bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int if (!index.isValid()) return false; - if (role == Qt::CheckStateRole) { - TestTreeItem *item = static_cast(index.internalPointer()); - Qt::CheckState old = item->checked(); - item->setChecked((Qt::CheckState)value.toInt()); - if (item->checked() != old) { - switch(item->type()) { + TestTreeItem *item = static_cast(index.internalPointer()); + if (item && item->setData(index.column(), value, role)) { + emit dataChanged(index, index); + if (role == Qt::CheckStateRole) { + switch (item->type()) { case TestTreeItem::TEST_CLASS: - emit dataChanged(index, index); - if (item->childCount() > 0) { + if (item->childCount() > 0) emit dataChanged(index.child(0, 0), index.child(item->childCount() - 1, 0)); - } break; case TestTreeItem::TEST_FUNCTION: - emit dataChanged(index, index); emit dataChanged(index.parent(), index.parent()); break; default: // avoid warning regarding unhandled enum member break; } - return true; } + return true; } return false; } diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 7a7deaeb135..7bcbe5e8b10 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -27,15 +27,6 @@ #include #include -namespace { - enum ItemRole { -// AnnotationRole = Qt::UserRole + 1, - LinkRole = Qt::UserRole + 2, // can be removed if AnnotationRole comes back - ItalicRole, // used only inside the delegate - TypeRole - }; -} - namespace Autotest { namespace Internal { From 9a193f7a4c6d3a5a0a2b4174f31a581f9a15aea0 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 10 Sep 2015 15:03:36 +0200 Subject: [PATCH 146/200] Remove unused code Change-Id: I12eb0ea78355e651fc4d904171dcdf49907b35b5 Reviewed-by: David Schulz --- plugins/autotest/testtreemodel.cpp | 15 --------------- plugins/autotest/testtreemodel.h | 1 - 2 files changed, 16 deletions(-) diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index e6ff3a2b74c..e18cb437cac 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -521,21 +521,6 @@ QList TestTreeModel::getUnnamedQuickTestFunctions() const return QList(); } -QSet TestTreeModel::qmlFilesForProFile(const QString &proFile) const -{ - QSet filePaths; - CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); - if (TestTreeItem *unnamed = unnamedQuickTests()) { - for (int i = 0; i < unnamed->childCount(); ++i) { - const TestTreeItem *child = unnamed->child(i); - QList ppList = modelManager->projectPart(child->mainFile()); - if (ppList.size() && ppList.at(0)->projectFile == proFile) - filePaths.insert(child->filePath()); - } - } - return filePaths; -} - bool TestTreeModel::hasUnnamedQuickTests() const { for (int row = 0, count = m_quickTestRootItem->childCount(); row < count; ++row) diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 7bcbe5e8b10..83b6f89b18e 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -67,7 +67,6 @@ public: QString getMainFileForUnnamedQuickTest(const QString &qmlFile) const; void qmlFilesForMainFile(const QString &mainFile, QSet *filePaths) const; QList getUnnamedQuickTestFunctions() const; - QSet qmlFilesForProFile(const QString &proFile) const; bool hasUnnamedQuickTests() const; #ifdef WITH_TESTS From 55f3dcb6b56ac77f64073f64a99467c5c16285df Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 10 Sep 2015 15:32:12 +0200 Subject: [PATCH 147/200] Re-use QC's TreeItem/TreeModel for TestTreeItem/TestTreeModel Change-Id: Ied35f808311392dcace1dca35796223369b37e0b Reviewed-by: Niels Weber --- plugins/autotest/testtreeitem.cpp | 97 +++++--------- plugins/autotest/testtreeitem.h | 25 ++-- plugins/autotest/testtreemodel.cpp | 195 ++++++++--------------------- plugins/autotest/testtreemodel.h | 17 +-- 4 files changed, 93 insertions(+), 241 deletions(-) diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index bea7766287b..8e36d95577a 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -23,7 +23,6 @@ #include #include -#include #include @@ -31,11 +30,11 @@ namespace Autotest { namespace Internal { TestTreeItem::TestTreeItem(const QString &name, const QString &filePath, Type type) - : m_name(name), + : TreeItem( { name } ), + m_name(name), m_filePath(filePath), m_type(type), - m_line(0), - m_parent(0) + m_line(0) { switch (m_type) { case TEST_CLASS: @@ -53,35 +52,17 @@ TestTreeItem::~TestTreeItem() } TestTreeItem::TestTreeItem(const TestTreeItem &other) - : m_name(other.m_name), + : TreeItem( { other.m_name } ), + m_name(other.m_name), m_filePath(other.m_filePath), m_checked(other.m_checked), m_type(other.m_type), m_line(other.m_line), m_column(other.m_column), - m_mainFile(other.m_mainFile), - m_parent(0) + m_mainFile(other.m_mainFile) { - foreach (const TestTreeItem *child, other.m_children) - appendChild(new TestTreeItem(*child)); -} - -TestTreeItem *TestTreeItem::child(int row) const -{ - return m_children.at(row); -} - -TestTreeItem *TestTreeItem::parent() const -{ - return m_parent; -} - -void TestTreeItem::appendChild(TestTreeItem *child) -{ - QTC_ASSERT(child->m_parent == 0, return); - - child->m_parent = this; - m_children.append(child); + for (int row = 0, count = other.childCount(); row < count; ++row) + appendChild(new TestTreeItem(*childItem(row))); } static QIcon testTreeIcon(TestTreeItem::Type type) @@ -124,7 +105,7 @@ QVariant TestTreeItem::data(int /*column*/, int role) const case TEST_CLASS: return m_name.isEmpty() ? QVariant() : checked(); case TEST_FUNCTION: - if (m_parent && m_parent->name().isEmpty()) + if (parentItem() && parentItem()->name().isEmpty()) return QVariant(); return checked(); default: @@ -143,7 +124,7 @@ QVariant TestTreeItem::data(int /*column*/, int role) const case TEST_CLASS: return m_name.isEmpty(); case TEST_FUNCTION: - return m_parent ? m_parent->name().isEmpty() : false; + return parentItem() ? parentItem()->name().isEmpty() : false; default: return false; } @@ -163,34 +144,6 @@ bool TestTreeItem::setData(int /*column*/, const QVariant &data, int role) return false; } -int TestTreeItem::row() const -{ - if (m_parent) - return m_parent->m_children.indexOf(const_cast(this)); - return 0; -} - -int TestTreeItem::childCount() const -{ - return m_children.size(); -} - -void TestTreeItem::removeChildren() -{ - qDeleteAll(m_children); - m_children.clear(); -} - -bool TestTreeItem::removeChild(int row) -{ - if (row < 0 || row >= m_children.size()) - return false; - TestTreeItem *child = m_children.at(row); - m_children.removeAt(row); - delete child; - return true; -} - bool TestTreeItem::modifyContent(const TestTreeItem *modified) { bool hasBeenModified = false; @@ -222,14 +175,13 @@ void TestTreeItem::setChecked(const Qt::CheckState checkState) switch (m_type) { case TEST_FUNCTION: { m_checked = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked); - m_parent->revalidateCheckState(); + parentItem()->revalidateCheckState(); break; } case TEST_CLASS: { Qt::CheckState usedState = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked); - foreach (TestTreeItem *child, m_children) { - child->setChecked(usedState); - } + for (int row = 0, count = childCount(); row < count; ++row) + childItem(row)->setChecked(usedState); m_checked = usedState; } default: @@ -247,8 +199,8 @@ Qt::CheckState TestTreeItem::checked() const case TEST_SPECIALFUNCTION: return Qt::Unchecked; default: - if (m_parent) - return m_parent->m_checked; + if (parent()) + return parentItem()->m_checked; } return Qt::Unchecked; } @@ -256,18 +208,29 @@ Qt::CheckState TestTreeItem::checked() const QList TestTreeItem::getChildNames() const { QList names; - foreach (TestTreeItem *item, m_children) - names << item->name(); + for (int row = 0, count = childCount(); row < count; ++row) + names << childItem(row)->name(); return names; } +TestTreeItem *TestTreeItem::parentItem() const +{ + return static_cast(parent()); +} + +TestTreeItem *TestTreeItem::childItem(int row) const +{ + return static_cast(child(row)); +} + void TestTreeItem::revalidateCheckState() { - if (m_children.size() == 0) + if (childCount() == 0) return; bool foundChecked = false; bool foundUnchecked = false; - foreach (const TestTreeItem *child, m_children) { + for (int row = 0, count = childCount(); row < count; ++row) { + TestTreeItem *child = childItem(row); switch (child->type()) { case TEST_DATAFUNCTION: case TEST_SPECIALFUNCTION: diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index 8a442e7f842..34ac137e044 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -20,14 +20,12 @@ #ifndef TESTTREEITEM_H #define TESTTREEITEM_H +#include + #include #include #include -QT_BEGIN_NAMESPACE -class QVariant; -QT_END_NAMESPACE - namespace { enum ItemRole { LinkRole = Qt::UserRole + 2, // can be removed if AnnotationRole comes back @@ -39,7 +37,7 @@ namespace { namespace Autotest { namespace Internal { -class TestTreeItem +class TestTreeItem : public Utils::TreeItem { public: @@ -57,21 +55,12 @@ public: virtual ~TestTreeItem(); TestTreeItem(const TestTreeItem& other); - TestTreeItem *child(int row) const; - TestTreeItem *parent() const; - void appendChild(TestTreeItem *child); - QVariant data(int column, int role) const; - bool setData(int column, const QVariant &data, int role); - int row() const; - int childCount() const; - void removeChildren(); - bool removeChild(int row); + virtual QVariant data(int column, int role) const override; + virtual bool setData(int column, const QVariant &data, int role) override; bool modifyContent(const TestTreeItem *modified); const QString name() const { return m_name; } - void setName(const QString &name) { m_name = name; } const QString filePath() const { return m_filePath; } - void setFilePath(const QString &filePath) { m_filePath = filePath; } void setLine(unsigned line) { m_line = line;} unsigned line() const { return m_line; } void setColumn(unsigned column) { m_column = column; } @@ -82,6 +71,8 @@ public: Qt::CheckState checked() const; Type type() const { return m_type; } QList getChildNames() const; + TestTreeItem *parentItem() const; + TestTreeItem *childItem(int row) const; private: void revalidateCheckState(); @@ -93,8 +84,6 @@ private: unsigned m_line; unsigned m_column; QString m_mainFile; - TestTreeItem *m_parent; - QList m_children; }; struct TestCodeLocationAndType { diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index e18cb437cac..2f7366b3793 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -37,15 +37,14 @@ namespace Autotest { namespace Internal { TestTreeModel::TestTreeModel(QObject *parent) : - QAbstractItemModel(parent), - m_rootItem(new TestTreeItem(QString(), QString(), TestTreeItem::ROOT)), + TreeModel(parent), m_autoTestRootItem(new TestTreeItem(tr("Auto Tests"), QString(), TestTreeItem::ROOT)), m_quickTestRootItem(new TestTreeItem(tr("Qt Quick Tests"), QString(), TestTreeItem::ROOT)), m_parser(new TestCodeParser(this)), m_connectionsInitialized(false) { - m_rootItem->appendChild(m_autoTestRootItem); - m_rootItem->appendChild(m_quickTestRootItem); + rootItem()->appendChild(m_autoTestRootItem); + rootItem()->appendChild(m_quickTestRootItem); connect(m_parser, &TestCodeParser::cacheCleared, this, &TestTreeModel::removeAllTestItems, Qt::QueuedConnection); @@ -85,7 +84,6 @@ TestTreeModel *TestTreeModel::instance() TestTreeModel::~TestTreeModel() { - delete m_rootItem; m_instance = 0; } @@ -126,66 +124,6 @@ void TestTreeModel::disableParsing() m_parser->setState(TestCodeParser::Disabled); } -QModelIndex TestTreeModel::index(int row, int column, const QModelIndex &parent) const -{ - if (!hasIndex(row, column, parent)) - return QModelIndex(); - - TestTreeItem *parentItem = parent.isValid() - ? static_cast(parent.internalPointer()) - : m_rootItem; - - TestTreeItem *childItem = parentItem->child(row); - return childItem ? createIndex(row, column, childItem) : QModelIndex(); -} - -QModelIndex TestTreeModel::parent(const QModelIndex &index) const -{ - if (!index.isValid()) - return QModelIndex(); - - TestTreeItem *childItem = static_cast(index.internalPointer()); - TestTreeItem *parentItem = childItem->parent(); - - if (parentItem == m_rootItem) - return QModelIndex(); - - return createIndex(parentItem->row(), 0, parentItem); -} - -bool TestTreeModel::hasChildren(const QModelIndex &parent) const -{ - if (!parent.isValid()) - return true; - - TestTreeItem *item = static_cast(parent.internalPointer()); - return item->childCount() > 0; -} - -int TestTreeModel::rowCount(const QModelIndex &parent) const -{ - TestTreeItem *parentItem = parent.isValid() - ? static_cast(parent.internalPointer()) : m_rootItem; - return parentItem->childCount(); -} - -int TestTreeModel::columnCount(const QModelIndex &) const -{ - return 1; -} - -QVariant TestTreeModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - TestTreeItem *item = static_cast(index.internalPointer()); - if (!item) - return QVariant(); - - return item->data(index.column(), role); -} - bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!index.isValid()) @@ -217,14 +155,14 @@ Qt::ItemFlags TestTreeModel::flags(const QModelIndex &index) const if (!index.isValid()) return Qt::ItemIsEnabled | Qt::ItemIsSelectable; - TestTreeItem *item = static_cast(index.internalPointer()); + TestTreeItem *item = static_cast(itemForIndex(index)); switch(item->type()) { case TestTreeItem::TEST_CLASS: if (item->name().isEmpty()) return Qt::ItemIsEnabled | Qt::ItemIsSelectable; return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsTristate | Qt::ItemIsUserCheckable; case TestTreeItem::TEST_FUNCTION: - if (item->parent()->name().isEmpty()) + if (item->parentItem()->name().isEmpty()) return Qt::ItemIsEnabled | Qt::ItemIsSelectable; return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable; case TestTreeItem::ROOT: @@ -236,26 +174,6 @@ Qt::ItemFlags TestTreeModel::flags(const QModelIndex &index) const } } -bool TestTreeModel::removeRows(int row, int count, const QModelIndex &parent) -{ - if (!parent.isValid()) - return false; - TestTreeItem *parentItem = static_cast(parent.internalPointer()); - if (!parentItem) - return false; - - bool subItemsSuccess = true; - bool itemSuccess = true; - for (int i = row + count - 1; i >= row; --i) { - QModelIndex child = index(i, 0, parent); - subItemsSuccess &= removeRows(0, rowCount(child), child); - beginRemoveRows(parent, i, i); - itemSuccess &= parentItem->removeChild(i); - endRemoveRows(); - } - return subItemsSuccess && itemSuccess; -} - bool TestTreeModel::hasTests() const { return m_autoTestRootItem->childCount() > 0 || m_quickTestRootItem->childCount() > 0; @@ -271,7 +189,7 @@ QList TestTreeModel::getAllTestCases() const // get all Auto Tests for (int row = 0, count = m_autoTestRootItem->childCount(); row < count; ++row) { - const TestTreeItem *child = m_autoTestRootItem->child(row); + const TestTreeItem *child = m_autoTestRootItem->childItem(row); TestConfiguration *tc = new TestConfiguration(child->name(), QStringList(), child->childCount()); @@ -283,11 +201,11 @@ QList TestTreeModel::getAllTestCases() const // get all Quick Tests QMap foundMains; for (int row = 0, count = m_quickTestRootItem->childCount(); row < count; ++row) { - TestTreeItem *child = m_quickTestRootItem->child(row); + const TestTreeItem *child = m_quickTestRootItem->childItem(row); // unnamed Quick Tests must be handled separately if (child->name().isEmpty()) { for (int childRow = 0, ccount = child->childCount(); childRow < ccount; ++ childRow) { - const TestTreeItem *grandChild = child->child(childRow); + const TestTreeItem *grandChild = child->childItem(childRow); const QString mainFile = grandChild->mainFile(); foundMains.insert(mainFile, foundMains.contains(mainFile) ? foundMains.value(mainFile) + 1 : 1); @@ -322,7 +240,7 @@ QList TestTreeModel::getSelectedTests() const TestConfiguration *testConfiguration = 0; for (int row = 0, count = m_autoTestRootItem->childCount(); row < count; ++row) { - TestTreeItem *child = m_autoTestRootItem->child(row); + const TestTreeItem *child = m_autoTestRootItem->childItem(row); switch (child->checked()) { case Qt::Unchecked: @@ -339,7 +257,7 @@ QList TestTreeModel::getSelectedTests() const int grandChildCount = child->childCount(); QStringList testCases; for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) { - const TestTreeItem *grandChild = child->child(grandChildRow); + const TestTreeItem *grandChild = child->childItem(grandChildRow); if (grandChild->checked() == Qt::Checked) testCases << grandChild->name(); } @@ -359,7 +277,7 @@ QList TestTreeModel::getSelectedTests() const if (TestTreeItem *unnamed = unnamedQuickTests()) { for (int childRow = 0, ccount = unnamed->childCount(); childRow < ccount; ++ childRow) { - const TestTreeItem *grandChild = unnamed->child(childRow); + const TestTreeItem *grandChild = unnamed->childItem(childRow); const QString mainFile = grandChild->mainFile(); if (foundMains.contains(mainFile)) { QTC_ASSERT(testConfiguration, @@ -378,7 +296,7 @@ QList TestTreeModel::getSelectedTests() const } for (int row = 0, count = m_quickTestRootItem->childCount(); row < count; ++row) { - TestTreeItem *child = m_quickTestRootItem->child(row); + const TestTreeItem *child = m_quickTestRootItem->childItem(row); // unnamed Quick Tests have been handled separately already if (child->name().isEmpty()) continue; @@ -393,11 +311,10 @@ QList TestTreeModel::getSelectedTests() const QStringList testFunctions; int grandChildCount = child->childCount(); for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) { - const TestTreeItem *grandChild = child->child(grandChildRow); + const TestTreeItem *grandChild = child->childItem(grandChildRow); if (grandChild->type() != TestTreeItem::TEST_FUNCTION) continue; - if (grandChild->checked() == Qt::Checked) - testFunctions << child->name() + QLatin1String("::") + grandChild->name(); + testFunctions << child->name() + QLatin1String("::") + grandChild->name(); } TestConfiguration *tc; if (foundMains.contains(child->mainFile())) { @@ -442,7 +359,8 @@ TestConfiguration *TestTreeModel::getTestConfiguration(const TestTreeItem *item) // Quick Test TestCase QStringList testFunctions; for (int row = 0, count = item->childCount(); row < count; ++row) { - testFunctions << item->name() + QLatin1String("::") + item->child(row)->name(); + testFunctions << item->name() + QLatin1String("::") + + item->childItem(row)->name(); } config = new TestConfiguration(QString(), testFunctions); config->setMainFilePath(item->mainFile()); @@ -456,7 +374,7 @@ TestConfiguration *TestTreeModel::getTestConfiguration(const TestTreeItem *item) break; } case TestTreeItem::TEST_FUNCTION: { - const TestTreeItem *parent = item->parent(); + const TestTreeItem *parent = item->parentItem(); if (parent->parent() == m_quickTestRootItem) { // it's a Quick Test function of a named TestCase QStringList testFunction(parent->name() + QLatin1String("::") + item->name()); @@ -472,8 +390,8 @@ TestConfiguration *TestTreeModel::getTestConfiguration(const TestTreeItem *item) break; } case TestTreeItem::TEST_DATATAG: { - const TestTreeItem *function = item->parent(); - const TestTreeItem *parent = function ? function->parent() : 0; + const TestTreeItem *function = item->parentItem(); + const TestTreeItem *parent = function ? function->parentItem() : 0; if (!parent) return 0; const QString functionWithTag = function->name() + QLatin1Char(':') + item->name(); @@ -494,7 +412,7 @@ QString TestTreeModel::getMainFileForUnnamedQuickTest(const QString &qmlFile) co const TestTreeItem *unnamed = unnamedQuickTests(); const int count = unnamed ? unnamed->childCount() : 0; for (int row = 0; row < count; ++row) { - const TestTreeItem *child = unnamed->child(row); + const TestTreeItem *child = unnamed->childItem(row); if (qmlFile == child->filePath()) return child->mainFile(); } @@ -503,11 +421,11 @@ QString TestTreeModel::getMainFileForUnnamedQuickTest(const QString &qmlFile) co void TestTreeModel::qmlFilesForMainFile(const QString &mainFile, QSet *filePaths) const { - TestTreeItem *unnamed = unnamedQuickTests(); + const TestTreeItem *unnamed = unnamedQuickTests(); if (!unnamed) return; - for (int i = 0; i < unnamed->childCount(); ++i) { - const TestTreeItem *child = unnamed->child(i); + for (int row = 0, count = unnamed->childCount(); row < count; ++row) { + const TestTreeItem *child = unnamed->childItem(row); if (child->mainFile() == mainFile) filePaths->insert(child->filePath()); } @@ -515,7 +433,7 @@ void TestTreeModel::qmlFilesForMainFile(const QString &mainFile, QSet * QList TestTreeModel::getUnnamedQuickTestFunctions() const { - TestTreeItem *unnamed = unnamedQuickTests(); + const TestTreeItem *unnamed = unnamedQuickTests(); if (unnamed) return unnamed->getChildNames(); return QList(); @@ -524,7 +442,7 @@ QList TestTreeModel::getUnnamedQuickTestFunctions() const bool TestTreeModel::hasUnnamedQuickTests() const { for (int row = 0, count = m_quickTestRootItem->childCount(); row < count; ++row) - if (m_quickTestRootItem->child(row)->name().isEmpty()) + if (m_quickTestRootItem->childItem(row)->name().isEmpty()) return true; return false; } @@ -532,7 +450,7 @@ bool TestTreeModel::hasUnnamedQuickTests() const TestTreeItem *TestTreeModel::unnamedQuickTests() const { for (int row = 0, count = m_quickTestRootItem->childCount(); row < count; ++row) { - TestTreeItem *child = m_quickTestRootItem->child(row); + TestTreeItem *child = m_quickTestRootItem->childItem(row); if (child->name().isEmpty()) return child; } @@ -545,26 +463,21 @@ void TestTreeModel::removeUnnamedQuickTests(const QString &filePath) if (!unnamedQT) return; - const QModelIndex unnamedQTIndex = index(1, 0).child(unnamedQT->row(), 0); for (int childRow = unnamedQT->childCount() - 1; childRow >= 0; --childRow) { - const TestTreeItem *child = unnamedQT->child(childRow); + TestTreeItem *child = unnamedQT->childItem(childRow); if (filePath == child->filePath()) - removeRow(childRow, unnamedQTIndex); + delete takeItem(child); } if (unnamedQT->childCount() == 0) - removeRow(unnamedQT->row(), unnamedQTIndex.parent()); + delete takeItem(unnamedQT); emit testTreeModelChanged(); } void TestTreeModel::addTestTreeItem(TestTreeItem *item, TestTreeModel::Type type) { TestTreeItem *parent = rootItemForType(type); - QModelIndex index = rootIndexForType(type); - - beginInsertRows(index, parent->childCount(), parent->childCount()); parent->appendChild(item); - endInsertRows(); emit testTreeModelChanged(); } @@ -578,9 +491,6 @@ void TestTreeModel::updateUnnamedQuickTest(const QString &mainFile, addTestTreeItem(new TestTreeItem(QString(), QString(), TestTreeItem::TEST_CLASS), QuickTest); TestTreeItem *unnamed = unnamedQuickTests(); - QModelIndex unnamedIndex = index(unnamed->row(), 0, rootIndexForType(QuickTest)); - - beginInsertRows(unnamedIndex, unnamed->childCount(), unnamed->childCount() + functions.size()); foreach (const QString &functionName, functions.keys()) { const TestCodeLocationAndType locationAndType = functions.value(functionName); TestTreeItem *testFunction = new TestTreeItem(functionName, locationAndType.m_name, @@ -590,7 +500,6 @@ void TestTreeModel::updateUnnamedQuickTest(const QString &mainFile, testFunction->setMainFile(mainFile); unnamed->appendChild(testFunction); } - endInsertRows(); } void TestTreeModel::modifyTestTreeItem(TestTreeItem *item, TestTreeModel::Type type, const QStringList &files) @@ -602,12 +511,12 @@ void TestTreeModel::modifyTestTreeItem(TestTreeItem *item, TestTreeModel::Type t if (unnamed == item) // no need to update or delete return; - index = index.child(unnamed->row(), 0); + index = indexForItem(unnamed); modifyTestSubtree(index, item); } } else { for (int row = 0; row < parent->childCount(); ++row) { - if (files.contains(parent->child(row)->filePath())) { + if (files.contains(parent->childItem(row)->filePath())) { index = index.child(row, 0); modifyTestSubtree(index, item); break; @@ -621,23 +530,21 @@ void TestTreeModel::modifyTestTreeItem(TestTreeItem *item, TestTreeModel::Type t void TestTreeModel::removeAllTestItems() { - beginResetModel(); m_autoTestRootItem->removeChildren(); m_quickTestRootItem->removeChildren(); - endResetModel(); emit testTreeModelChanged(); } void TestTreeModel::removeTestTreeItems(const QString &filePath, Type type) { bool removed = false; - const QModelIndex rootIndex = rootIndexForType(type); - const int count = rowCount(rootIndex); - for (int row = count - 1; row >= 0; --row) { - const QModelIndex childIndex = rootIndex.child(row, 0); - TestTreeItem *childItem = static_cast(childIndex.internalPointer()); - if (filePath == childItem->filePath()) - removed |= removeRow(row, rootIndex); + const TestTreeItem *rootItem = rootItemForType(type); + for (int row = rootItem->childCount() - 1; row >= 0; --row) { + TestTreeItem *childItem = rootItem->childItem(row); + if (filePath == childItem->filePath()) { + delete takeItem(childItem); + removed = true; + } } if (removed) emit testTreeModelChanged(); @@ -670,7 +577,7 @@ void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, const Test if (!toBeModifiedIndex.isValid()) return; - TestTreeItem *toBeModifiedItem = static_cast(toBeModifiedIndex.internalPointer()); + TestTreeItem *toBeModifiedItem = static_cast(itemForIndex(toBeModifiedIndex)); if (toBeModifiedItem->modifyContent(newItem)) emit dataChanged(toBeModifiedIndex, toBeModifiedIndex, QVector() << Qt::DisplayRole << Qt::ToolTipRole << LinkRole); @@ -683,7 +590,7 @@ void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, const Test // TODO might still fail for duplicate entries QHash checkStates; for (int row = 0; row < childCount; ++row) { - const TestTreeItem *child = toBeModifiedItem->child(row); + const TestTreeItem *child = toBeModifiedItem->childItem(row); checkStates.insert(child->name(), child->checked()); } @@ -691,19 +598,18 @@ void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, const Test processChildren(toBeModifiedIndex, newItem, childCount, checkStates); // add additional items for (int row = childCount; row < newChildCount; ++row) { - TestTreeItem *newChild = newItem->child(row); + const TestTreeItem *newChild = newItem->childItem(row); TestTreeItem *toBeAdded = new TestTreeItem(*newChild); if (checkStates.contains(toBeAdded->name()) && checkStates.value(toBeAdded->name()) != Qt::Checked) toBeAdded->setChecked(checkStates.value(toBeAdded->name())); - beginInsertRows(toBeModifiedIndex, row, row); toBeModifiedItem->appendChild(toBeAdded); - endInsertRows(); } } else { processChildren(toBeModifiedIndex, newItem, newChildCount, checkStates); // remove rest of the items - removeRows(newChildCount, childCount - newChildCount, toBeModifiedIndex); + for (int row = childCount - 1; row > newChildCount; --row) + delete takeItem(toBeModifiedItem->childItem(row)); } emit testTreeModelChanged(); } @@ -713,12 +619,13 @@ void TestTreeModel::processChildren(QModelIndex &parentIndex, const TestTreeItem const QHash &checkStates) { static QVector modificationRoles = QVector() << Qt::DisplayRole - << Qt::ToolTipRole << LinkRole; - TestTreeItem *toBeModifiedItem = static_cast(parentIndex.internalPointer()); + << Qt::ToolTipRole + << LinkRole; + TestTreeItem *toBeModifiedItem = static_cast(itemForIndex(parentIndex)); for (int row = 0; row < upperBound; ++row) { QModelIndex child = parentIndex.child(row, 0); - TestTreeItem *toBeModifiedChild = toBeModifiedItem->child(row); - TestTreeItem *modifiedChild = newItem->child(row); + TestTreeItem *toBeModifiedChild = toBeModifiedItem->childItem(row); + const TestTreeItem *modifiedChild = newItem->childItem(row); if (toBeModifiedChild->modifyContent(modifiedChild)) emit dataChanged(child, child, modificationRoles); @@ -730,7 +637,7 @@ void TestTreeModel::processChildren(QModelIndex &parentIndex, const TestTreeItem const int count = modifiedChild->childCount(); beginInsertRows(child, 0, count); for (int childRow = 0; childRow < count; ++childRow) - toBeModifiedChild->appendChild(new TestTreeItem(*modifiedChild->child(childRow))); + toBeModifiedChild->appendChild(new TestTreeItem(*modifiedChild->childItem(childRow))); endInsertRows(); } @@ -818,8 +725,8 @@ bool TestTreeSortFilterModel::lessThan(const QModelIndex &left, const QModelInde if (leftItem->type() == TestTreeItem::ROOT) return left.row() > right.row(); - const QString leftVal = m_sourceModel->data(left).toString(); - const QString rightVal = m_sourceModel->data(right).toString(); + const QString leftVal = m_sourceModel->data(left, Qt::DisplayRole).toString(); + const QString rightVal = m_sourceModel->data(right, Qt::DisplayRole).toString(); // unnamed Quick Tests will always be listed first if (leftVal == tr(Constants::UNNAMED_QUICKTESTS)) diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 83b6f89b18e..5c51648ed50 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -24,7 +24,8 @@ #include -#include +#include + #include namespace Autotest { @@ -35,7 +36,7 @@ class TestCodeParser; class TestInfo; class TestTreeItem; -class TestTreeModel : public QAbstractItemModel +class TestTreeModel : public Utils::TreeModel { Q_OBJECT public: @@ -49,15 +50,8 @@ public: void enableParsing(); void disableParsing(); - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; - QModelIndex parent(const QModelIndex &index) const; - bool hasChildren(const QModelIndex &parent) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - bool setData(const QModelIndex &index, const QVariant &value, int role); - Qt::ItemFlags flags(const QModelIndex &index) const; - bool removeRows(int row, int count, const QModelIndex &parent); + bool setData(const QModelIndex &index, const QVariant &value, int role) override; + Qt::ItemFlags flags(const QModelIndex &index) const override; TestCodeParser *parser() const { return m_parser; } bool hasTests() const; @@ -98,7 +92,6 @@ private: void processChildren(QModelIndex &parentIndex, const TestTreeItem *newItem, const int upperBound, const QHash &checkStates); - TestTreeItem *m_rootItem; TestTreeItem *m_autoTestRootItem; TestTreeItem *m_quickTestRootItem; TestCodeParser *m_parser; From 17fbe92100d194250dd7567232b58830d9d447e4 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 23 Sep 2015 07:14:25 +0200 Subject: [PATCH 148/200] Simplify conversion from/to Result::Type Additionally rename enum value UNKNOWN to INVALID. Change-Id: I08dc4e371afb576db10716eda00ff6368f9d2311 Reviewed-by: Niels Weber --- plugins/autotest/testresult.cpp | 72 +++++------------------- plugins/autotest/testresult.h | 13 +++-- plugins/autotest/testresultmodel.cpp | 2 +- plugins/autotest/testxmloutputreader.cpp | 4 +- 4 files changed, 24 insertions(+), 67 deletions(-) diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp index 0ce300eade5..8859d8fb1a1 100644 --- a/plugins/autotest/testresult.cpp +++ b/plugins/autotest/testresult.cpp @@ -61,56 +61,23 @@ Result::Type TestResult::resultFromString(const QString &resultString) if (resultString == QLatin1String("bfail")) return Result::BLACKLISTED_FAIL; qDebug("Unexpected test result: %s", qPrintable(resultString)); - return Result::UNKNOWN; + return Result::INVALID; } Result::Type TestResult::toResultType(int rt) { - switch(rt) { - case Result::PASS: - return Result::PASS; - case Result::FAIL: - return Result::FAIL; - case Result::EXPECTED_FAIL: - return Result::EXPECTED_FAIL; - case Result::UNEXPECTED_PASS: - return Result::UNEXPECTED_PASS; - case Result::SKIP: - return Result::SKIP; - case Result::BLACKLISTED_PASS: - return Result::BLACKLISTED_PASS; - case Result::BLACKLISTED_FAIL: - return Result::BLACKLISTED_FAIL; - case Result::BENCHMARK: - return Result::BENCHMARK; - case Result::MESSAGE_DEBUG: - return Result::MESSAGE_DEBUG; - case Result::MESSAGE_WARN: - return Result::MESSAGE_WARN; - case Result::MESSAGE_FATAL: - return Result::MESSAGE_FATAL; - case Result::MESSAGE_INTERNAL: - return Result::MESSAGE_INTERNAL; - case Result::MESSAGE_TEST_CASE_START: - return Result::MESSAGE_TEST_CASE_START; - case Result::MESSAGE_TEST_CASE_SUCCESS: - return Result::MESSAGE_TEST_CASE_SUCCESS; - case Result::MESSAGE_TEST_CASE_WARN: - return Result::MESSAGE_TEST_CASE_WARN; - case Result::MESSAGE_TEST_CASE_FAIL: - return Result::MESSAGE_TEST_CASE_FAIL; - case Result::MESSAGE_TEST_CASE_END: - return Result::MESSAGE_TEST_CASE_END; - case Result::MESSAGE_CURRENT_TEST: - return Result::MESSAGE_CURRENT_TEST; - default: - return Result::UNKNOWN; - } + if (rt < Result::FIRST_TYPE || rt > Result::LAST_TYPE) + return Result::INVALID; + + return (Result::Type)rt; } QString TestResult::resultToString(const Result::Type type) { - switch(type) { + if (type >= Result::INTERNAL_MESSAGES_BEGIN && type <= Result::INTERNAL_MESSAGES_END) + return QString(); + + switch (type) { case Result::PASS: return QLatin1String("PASS"); case Result::FAIL: @@ -129,14 +96,6 @@ QString TestResult::resultToString(const Result::Type type) return QLatin1String("WARN"); case Result::MESSAGE_FATAL: return QLatin1String("FATAL"); - case Result::MESSAGE_INTERNAL: - case Result::MESSAGE_TEST_CASE_START: - case Result::MESSAGE_TEST_CASE_SUCCESS: - case Result::MESSAGE_TEST_CASE_WARN: - case Result::MESSAGE_TEST_CASE_FAIL: - case Result::MESSAGE_TEST_CASE_END: - case Result::MESSAGE_CURRENT_TEST: - return QString(); case Result::BLACKLISTED_PASS: return QLatin1String("BPASS"); case Result::BLACKLISTED_FAIL: @@ -148,7 +107,10 @@ QString TestResult::resultToString(const Result::Type type) QColor TestResult::colorForType(const Result::Type type) { - switch(type) { + if (type >= Result::INTERNAL_MESSAGES_BEGIN && type <= Result::INTERNAL_MESSAGES_END) + return QColor("transparent"); + + switch (type) { case Result::PASS: return QColor("#009900"); case Result::FAIL: @@ -169,14 +131,6 @@ QColor TestResult::colorForType(const Result::Type type) return QColor("#d0bb00"); case Result::MESSAGE_FATAL: return QColor("#640000"); - case Result::MESSAGE_INTERNAL: - case Result::MESSAGE_TEST_CASE_START: - case Result::MESSAGE_TEST_CASE_SUCCESS: - case Result::MESSAGE_TEST_CASE_WARN: - case Result::MESSAGE_TEST_CASE_FAIL: - case Result::MESSAGE_TEST_CASE_END: - case Result::MESSAGE_CURRENT_TEST: - return QColor("transparent"); default: return QColor("#000000"); } diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index e1e6e770d0e..cc10cf5fe32 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -29,7 +29,7 @@ namespace Internal { namespace Result{ enum Type { - PASS, + PASS, FIRST_TYPE = PASS, FAIL, EXPECTED_FAIL, UNEXPECTED_PASS, @@ -40,14 +40,17 @@ enum Type { MESSAGE_DEBUG, MESSAGE_WARN, MESSAGE_FATAL, - MESSAGE_INTERNAL, + + MESSAGE_INTERNAL, INTERNAL_MESSAGES_BEGIN = MESSAGE_INTERNAL, MESSAGE_TEST_CASE_START, MESSAGE_TEST_CASE_SUCCESS, MESSAGE_TEST_CASE_WARN, MESSAGE_TEST_CASE_FAIL, MESSAGE_TEST_CASE_END, - MESSAGE_CURRENT_TEST, - UNKNOWN // ??? + MESSAGE_CURRENT_TEST, INTERNAL_MESSAGES_END = MESSAGE_CURRENT_TEST, + + INVALID, + LAST_TYPE = INVALID }; } @@ -57,7 +60,7 @@ public: TestResult(const QString &className = QString(), const QString &testCase = QString(), const QString &dataTag = QString(), - Result::Type result = Result::UNKNOWN, const QString &description = QString()); + Result::Type result = Result::INVALID, const QString &description = QString()); QString className() const { return m_class; } QString testCase() const { return m_case; } diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index dd46554043c..5a09b5670b9 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -275,7 +275,7 @@ void TestResultFilterModel::enableAllResultTypes() m_enabled << Result::PASS << Result::FAIL << Result::EXPECTED_FAIL << Result::UNEXPECTED_PASS << Result::SKIP << Result::MESSAGE_DEBUG << Result::MESSAGE_WARN << Result::MESSAGE_INTERNAL - << Result::MESSAGE_FATAL << Result::UNKNOWN << Result::BLACKLISTED_PASS + << Result::MESSAGE_FATAL << Result::INVALID << Result::BLACKLISTED_PASS << Result::BLACKLISTED_FAIL << Result::BENCHMARK << Result::MESSAGE_CURRENT_TEST << Result::MESSAGE_TEST_CASE_START << Result::MESSAGE_TEST_CASE_SUCCESS << Result::MESSAGE_TEST_CASE_WARN diff --git a/plugins/autotest/testxmloutputreader.cpp b/plugins/autotest/testxmloutputreader.cpp index f137b8d1d6e..b3221f123d1 100644 --- a/plugins/autotest/testxmloutputreader.cpp +++ b/plugins/autotest/testxmloutputreader.cpp @@ -195,7 +195,7 @@ void TestXmlOutputReader::processOutput() static QString className; static QString testCase; static QString dataTag; - static Result::Type result = Result::UNKNOWN; + static Result::Type result = Result::INVALID; static QString description; static QString file; static int lineNumber = 0; @@ -223,7 +223,7 @@ void TestXmlOutputReader::processOutput() description = QString(); duration = QString(); file = QString(); - result = Result::UNKNOWN; + result = Result::INVALID; lineNumber = 0; readingDescription = false; testResultCreated(new TestResult(QString(), QString(), QString(), Result::MESSAGE_CURRENT_TEST, From 23bdcf77b6ee8c0799934c79db2d10564983f838 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 23 Sep 2015 07:47:12 +0200 Subject: [PATCH 149/200] Use QXmlStreamReader to parse test run output Using the QXmlStreamReader will be easier to extend current functionality and should be more robust than parsing on our own. Change-Id: I9e1df7083a1af7681987f3971550e19a35b29df9 Reviewed-by: David Schulz --- plugins/autotest/testresult.cpp | 20 +- plugins/autotest/testresult.h | 8 +- plugins/autotest/testxmloutputreader.cpp | 314 +++++++++++------------ plugins/autotest/testxmloutputreader.h | 9 +- 4 files changed, 176 insertions(+), 175 deletions(-) diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp index 8859d8fb1a1..293145f3e95 100644 --- a/plugins/autotest/testresult.cpp +++ b/plugins/autotest/testresult.cpp @@ -23,18 +23,20 @@ namespace Autotest { namespace Internal { FaultyTestResult::FaultyTestResult(Result::Type result, const QString &description) - : TestResult(QString(), QString(), QString(), result, description) +{ + setResult(result); + setDescription(description); +} + +TestResult::TestResult() + : TestResult(QString()) { } -TestResult::TestResult(const QString &className, const QString &testCase, const QString &dataTag, - Result::Type result, const QString &description) - : m_class(className), - m_case(testCase), - m_dataTag(dataTag), - m_result(result), - m_description(description), - m_line(0) +TestResult::TestResult(const QString &className) + : m_class(className) + , m_result(Result::INVALID) + , m_line(0) { } diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index cc10cf5fe32..1ad8d51a4ad 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -57,10 +57,8 @@ enum Type { class TestResult { public: - - TestResult(const QString &className = QString(), const QString &testCase = QString(), - const QString &dataTag = QString(), - Result::Type result = Result::INVALID, const QString &description = QString()); + TestResult(); + TestResult(const QString &className); QString className() const { return m_class; } QString testCase() const { return m_case; } @@ -74,6 +72,8 @@ public: void setFileName(const QString &fileName) { m_file = fileName; } void setLine(int line) { m_line = line; } void setResult(Result::Type type) { m_result = type; } + void setTestCase(const QString &testCase) { m_case = testCase; } + void setDataTag(const QString &dataTag) { m_dataTag = dataTag; } static Result::Type resultFromString(const QString &resultString); static Result::Type toResultType(int rt); diff --git a/plugins/autotest/testxmloutputreader.cpp b/plugins/autotest/testxmloutputreader.cpp index b3221f123d1..8bff8557722 100644 --- a/plugins/autotest/testxmloutputreader.cpp +++ b/plugins/autotest/testxmloutputreader.cpp @@ -21,6 +21,7 @@ #include "testresult.h" #include +#include #include #include @@ -60,44 +61,6 @@ static QString constructSourceFilePath(const QString &path, const QString &fileP return QFileInfo(path, filePath).canonicalFilePath(); } -static bool xmlStartsWith(const QString &code, const QString &start, QString &result) -{ - if (code.startsWith(start)) { - result = code.mid(start.length()); - result = result.left(result.indexOf(QLatin1Char('"'))); - result = result.left(result.indexOf(QLatin1String(""), index) - index); - return !result.isEmpty(); - } - return false; -} - -static bool xmlExtractTypeFileLine(const QString &code, const QString &tagStart, - Result::Type &result, QString &file, int &line) -{ - if (code.startsWith(tagStart)) { - int start = code.indexOf(QLatin1String(" type=\"")) + 7; - result = TestResult::resultFromString( - code.mid(start, code.indexOf(QLatin1Char('"'), start) - start)); - start = code.indexOf(QLatin1String(" file=\"")) + 7; - file = decode(code.mid(start, code.indexOf(QLatin1Char('"'), start) - start)); - start = code.indexOf(QLatin1String(" line=\"")) + 7; - line = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start).toInt(); - return true; - } - return false; -} - - // adapted from qplaintestlogger.cpp static QString formatResult(double value) { @@ -146,35 +109,24 @@ static QString formatResult(double value) return result; } -static bool xmlExtractBenchmarkInformation(const QString &code, const QString &tagStart, - QString &description) +static QString constructBenchmarkInformation(const QString &metric, double value, int iterations) { - if (code.startsWith(tagStart)) { - int start = code.indexOf(QLatin1String(" metric=\"")) + 9; - const QString metric = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start); - start = code.indexOf(QLatin1String(" value=\"")) + 8; - const double value = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start).toDouble(); - start = code.indexOf(QLatin1String(" iterations=\"")) + 13; - const int iterations = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start).toInt(); - QString metricsText; - if (metric == QLatin1String("WalltimeMilliseconds")) // default - metricsText = QLatin1String("msecs"); - else if (metric == QLatin1String("CPUTicks")) // -tickcounter - metricsText = QLatin1String("CPU ticks"); - else if (metric == QLatin1String("Events")) // -eventcounter - metricsText = QLatin1String("events"); - else if (metric == QLatin1String("InstructionReads")) // -callgrind - metricsText = QLatin1String("instruction reads"); - else if (metric == QLatin1String("CPUCycles")) // -perf - metricsText = QLatin1String("CPU cycles"); - description = QObject::tr("%1 %2 per iteration (total: %3, iterations: %4)") - .arg(formatResult(value)) - .arg(metricsText) - .arg(formatResult(value * (double)iterations)) - .arg(iterations); - return true; - } - return false; + QString metricsText; + if (metric == QLatin1String("WalltimeMilliseconds")) // default + metricsText = QLatin1String("msecs"); + else if (metric == QLatin1String("CPUTicks")) // -tickcounter + metricsText = QLatin1String("CPU ticks"); + else if (metric == QLatin1String("Events")) // -eventcounter + metricsText = QLatin1String("events"); + else if (metric == QLatin1String("InstructionReads")) // -callgrind + metricsText = QLatin1String("instruction reads"); + else if (metric == QLatin1String("CPUCycles")) // -perf + metricsText = QLatin1String("CPU cycles"); + return QObject::tr("%1 %2 per iteration (total: %3, iterations: %4)") + .arg(formatResult(value)) + .arg(metricsText) + .arg(formatResult(value * (double)iterations)) + .arg(iterations); } TestXmlOutputReader::TestXmlOutputReader(QProcess *testApplication) @@ -184,14 +136,24 @@ TestXmlOutputReader::TestXmlOutputReader(QProcess *testApplication) this, &TestXmlOutputReader::processOutput); } -TestXmlOutputReader::~TestXmlOutputReader() -{ -} +enum CDATAMode { + None, + DataTag, + Description, + QtVersion, + QTestVersion +}; void TestXmlOutputReader::processOutput() { if (!m_testApplication || m_testApplication->state() != QProcess::Running) return; + static QStringList validEndTags = { QStringLiteral("Incident"), + QStringLiteral("Message"), + QStringLiteral("BenchmarkResult"), + QStringLiteral("QtVersion"), + QStringLiteral("QTestVersion") }; + static CDATAMode cdataMode = None; static QString className; static QString testCase; static QString dataTag; @@ -200,98 +162,136 @@ void TestXmlOutputReader::processOutput() static QString file; static int lineNumber = 0; static QString duration; - static bool readingDescription = false; - static QString qtVersion; - static QString qtestVersion; - static QString benchmarkDescription; + static QXmlStreamReader xmlReader; while (m_testApplication->canReadLine()) { - // TODO Qt5 uses UTF-8 - while Qt4 uses ISO-8859-1 - could this be a problem? - const QString line = QString::fromUtf8(m_testApplication->readLine()).trimmed(); - if (line.isEmpty() || xmlStartsWith(line, QLatin1String(""), dataTag)) - continue; - if (xmlCData(line, QLatin1String(""), description)) { - if (!line.endsWith(QLatin1String(""))) - readingDescription = true; - continue; - } - if (xmlExtractTypeFileLine(line, QLatin1String(""))) { - TestResult *testResult = new TestResult(className, testCase, dataTag, result, description); - if (!file.isEmpty()) - file = constructSourceFilePath(m_testApplication->workingDirectory(), file, - m_testApplication->program()); - testResult->setFileName(file); - testResult->setLine(lineNumber); - testResultCreated(testResult); + xmlReader.addData(m_testApplication->readLine()); + while (!xmlReader.atEnd()) { + QXmlStreamReader::TokenType token = xmlReader.readNext(); + switch (token) { + case QXmlStreamReader::StartDocument: + className.clear(); + break; + case QXmlStreamReader::EndDocument: + xmlReader.clear(); + return; + case QXmlStreamReader::StartElement: { + const QString currentTag = xmlReader.name().toString(); + if (currentTag == QStringLiteral("TestCase")) { + className = xmlReader.attributes().value(QStringLiteral("name")).toString(); + QTC_ASSERT(!className.isEmpty(), continue); + auto testResult = new TestResult(className); + testResult->setResult(Result::MESSAGE_TEST_CASE_START); + testResult->setDescription(tr("Executing test case %1").arg(className)); + testResultCreated(testResult); + } else if (currentTag == QStringLiteral("TestFunction")) { + testCase = xmlReader.attributes().value(QStringLiteral("name")).toString(); + QTC_ASSERT(!testCase.isEmpty(), continue); + auto testResult = new TestResult(); + testResult->setResult(Result::MESSAGE_CURRENT_TEST); + testResult->setDescription(tr("Entering test function %1::%2").arg(className, + testCase)); + testResultCreated(testResult); + } else if (currentTag == QStringLiteral("Duration")) { + duration = xmlReader.attributes().value(QStringLiteral("msecs")).toString(); + QTC_ASSERT(!duration.isEmpty(), continue); + } else if (currentTag == QStringLiteral("Message") + || currentTag == QStringLiteral("Incident")) { + dataTag.clear(); + description.clear(); + duration.clear(); + file.clear(); + result = Result::INVALID; + lineNumber = 0; + const QXmlStreamAttributes &attributes = xmlReader.attributes(); + result = TestResult::resultFromString( + attributes.value(QStringLiteral("type")).toString()); + file = decode(attributes.value(QStringLiteral("file")).toString()); + if (!file.isEmpty()) + file = constructSourceFilePath(m_testApplication->workingDirectory(), file, + m_testApplication->program()); + lineNumber = attributes.value(QStringLiteral("line")).toInt(); + } else if (currentTag == QStringLiteral("BenchmarkResult")) { + const QXmlStreamAttributes &attributes = xmlReader.attributes(); + const QString metric = attributes.value(QStringLiteral("metrics")).toString(); + const double value = attributes.value(QStringLiteral("value")).toDouble(); + const int iterations = attributes.value(QStringLiteral("iterations")).toInt(); + description = constructBenchmarkInformation(metric, value, iterations); + result = Result::BENCHMARK; + } else if (currentTag == QStringLiteral("DataTag")) { + cdataMode = DataTag; + } else if (currentTag == QStringLiteral("Description")) { + cdataMode = Description; + } else if (currentTag == QStringLiteral("QtVersion")) { + result = Result::MESSAGE_INTERNAL; + cdataMode = QtVersion; + } else if (currentTag == QStringLiteral("QTestVersion")) { + result = Result::MESSAGE_INTERNAL; + cdataMode = QTestVersion; + } + break; } - continue; - } - if (xmlExtractBenchmarkInformation(line, QLatin1String("") || line == QLatin1String("")) { - TestResult *testResult = new TestResult(className, testCase, dataTag, result, description); - if (!file.isEmpty()) - file = constructSourceFilePath(m_testApplication->workingDirectory(), file, - m_testApplication->program()); - testResult->setFileName(file); - testResult->setLine(lineNumber); - testResultCreated(testResult); - description = QString(); - } else if (line == QLatin1String("") && !duration.isEmpty()) { - testResultCreated(new TestResult(className, testCase, QString(), Result::MESSAGE_INTERNAL, - QObject::tr("Execution took %1 ms.").arg(duration))); - emit increaseProgress(); - } else if (line == QLatin1String("") && !duration.isEmpty()) { - testResultCreated(new TestResult(className, QString(), QString(), Result::MESSAGE_TEST_CASE_END, - QObject::tr("Test execution took %1 ms.").arg(duration))); - } else if (readingDescription) { - if (line.endsWith(QLatin1String("]]>"))) { - description.append(QLatin1Char('\n')); - description.append(line.left(line.indexOf(QLatin1String("]]>")))); - readingDescription = false; - } else { - description.append(QLatin1Char('\n')); - description.append(line); + case QXmlStreamReader::Characters: { + QStringRef text = xmlReader.text().trimmed(); + if (text.isEmpty()) + break; + + switch (cdataMode) { + case DataTag: + dataTag = text.toString(); + break; + case Description: + if (!description.isEmpty()) + description.append(QLatin1Char('\n')); + description.append(text); + break; + case QtVersion: + description = tr("Qt version: %1").arg(text.toString()); + break; + case QTestVersion: + description = tr("QTest version: %1").arg(text.toString()); + break; + default: + QString message = QString::fromLatin1("unexpected cdatamode %1 for text \"%2\"") + .arg(cdataMode) + .arg(text.toString()); + QTC_ASSERT(false, qWarning() << message); + break; + } + break; + } + case QXmlStreamReader::EndElement: { + cdataMode = None; + const QStringRef currentTag = xmlReader.name(); + if (currentTag == QStringLiteral("TestFunction")) { + if (!duration.isEmpty()) { + auto testResult = new TestResult(className); + testResult->setTestCase(testCase); + testResult->setResult(Result::MESSAGE_INTERNAL); + testResult->setDescription(tr("Execution took %1 ms.").arg(duration)); + testResultCreated(testResult); + } + emit increaseProgress(); + } else if (currentTag == QStringLiteral("TestCase") && !duration.isEmpty()) { + auto testResult = new TestResult(className); + testResult->setResult(Result::MESSAGE_TEST_CASE_END); + testResult->setDescription(tr("Test execution took %1 ms.").arg(duration)); + testResultCreated(testResult); + } else if (validEndTags.contains(currentTag.toString())) { + auto testResult = new TestResult(className); + testResult->setTestCase(testCase); + testResult->setDataTag(dataTag); + testResult->setResult(result); + testResult->setFileName(file); + testResult->setLine(lineNumber); + testResult->setDescription(description); + testResultCreated(testResult); + } + break; + } + default: + break; } - } else if (xmlStartsWith(line, QLatin1String(""), qtVersion)) { - testResultCreated(new TestResult(className, QString(), QString(), Result::MESSAGE_INTERNAL, - QObject::tr("Qt version: %1").arg(qtVersion))); - } else if (xmlStartsWith(line, QLatin1String(""), qtestVersion)) { - testResultCreated(new TestResult(className, QString(), QString(), Result::MESSAGE_INTERNAL, - QObject::tr("QTest version: %1").arg(qtestVersion))); - } else { -// qDebug() << "Unhandled line:" << line; // TODO remove } } } diff --git a/plugins/autotest/testxmloutputreader.h b/plugins/autotest/testxmloutputreader.h index 6dfcef51ccc..feb99c46b21 100644 --- a/plugins/autotest/testxmloutputreader.h +++ b/plugins/autotest/testxmloutputreader.h @@ -24,10 +24,9 @@ #include #include +#include QT_BEGIN_NAMESPACE -class QXmlStreamReader; -class QIODevice; class QProcess; QT_END_NAMESPACE @@ -37,18 +36,18 @@ namespace Internal { class TestXmlOutputReader : public QObject { Q_OBJECT - public: TestXmlOutputReader(QProcess *testApplication); - ~TestXmlOutputReader(); public slots: void processOutput(); + signals: void testResultCreated(TestResult *testResult); void increaseProgress(); + private: - QProcess *m_testApplication; + QProcess *m_testApplication; // not owned }; } // namespace Internal From 1daf85a722dba7aa06f307ea34abb97e0bf8a0a6 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Fri, 9 Oct 2015 14:19:53 +0200 Subject: [PATCH 150/200] Quieten warning by the code model QDebug is considered a forward declared type only. Change-Id: Icd3d544dee04d81bb7087fe6f0153949afad3f10 Reviewed-by: Christian Stenger --- plugins/autotest/testxmloutputreader.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/autotest/testxmloutputreader.cpp b/plugins/autotest/testxmloutputreader.cpp index 8bff8557722..63fa9f92873 100644 --- a/plugins/autotest/testxmloutputreader.cpp +++ b/plugins/autotest/testxmloutputreader.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include From 0749d66362ff96b0792fefb9b7c79409cb6d02b5 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Wed, 14 Oct 2015 15:12:42 +0200 Subject: [PATCH 151/200] Fix warning about comparing an enum to an integer Change-Id: I2a35fa58c5e68d3bd2bb38599ddcf7c4e8e0deb2 Reviewed-by: Christian Stenger --- plugins/autotest/testtreeitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index 8e36d95577a..4dc78f3aa15 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -73,7 +73,7 @@ static QIcon testTreeIcon(TestTreeItem::Type type) QIcon(QLatin1String(":/images/func.png")), QIcon(QLatin1String(":/images/data.png")) }; - if (type >= sizeof(icons)) + if (static_cast(type) >= sizeof(icons)) return icons[2]; return icons[type]; } From 11a3479b2a944d429bdd89fdc4aa13f3ef9c9a8e Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 23 Oct 2015 17:33:40 +0200 Subject: [PATCH 152/200] Fix potential access beyond array end. Change-Id: I81b3903858a9072ba2a4ac9e2df572c02fdb9281 Reviewed-by: Christian Stenger --- plugins/autotest/testtreeitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index 4dc78f3aa15..6c29f886e85 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -73,7 +73,7 @@ static QIcon testTreeIcon(TestTreeItem::Type type) QIcon(QLatin1String(":/images/func.png")), QIcon(QLatin1String(":/images/data.png")) }; - if (static_cast(type) >= sizeof(icons)) + if (int(type) >= int(sizeof icons / sizeof *icons)) return icons[2]; return icons[type]; } From 33d1a8c3075712b9fac34a70ba136a012686a6fa Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 29 Oct 2015 10:20:53 +0100 Subject: [PATCH 153/200] Fix support for data tags Functions defined within the declaration or inside a namespace had no qualified name stored by the visitor. This lead to ignoring them when creating the respective TestTreeItem. Change-Id: Id57c0c492a0cba460aa2d47dc7283bb1ac6e4aa6 Reviewed-by: Nikolai Kosjar --- plugins/autotest/testvisitor.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/plugins/autotest/testvisitor.cpp b/plugins/autotest/testvisitor.cpp index 3fe84cb0776..7102476a7d1 100644 --- a/plugins/autotest/testvisitor.cpp +++ b/plugins/autotest/testvisitor.cpp @@ -177,15 +177,14 @@ bool TestDataFunctionVisitor::visit(CPlusPlus::FunctionDefinitionAST *ast) { if (ast->declarator) { CPlusPlus::DeclaratorIdAST *id = ast->declarator->core_declarator->asDeclaratorId(); - if (!id) + if (!id || !ast->symbol || ast->symbol->argumentCount() != 0) return false; - const QString prettyName = m_overview.prettyName(id->name->name); + CPlusPlus::LookupContext lc; + const QString prettyName = m_overview.prettyName(lc.fullyQualifiedName(ast->symbol)); // do not handle functions that aren't real test data functions - if (!prettyName.endsWith(QLatin1String("_data")) || !ast->symbol - || ast->symbol->argumentCount() != 0) { + if (!prettyName.endsWith(QLatin1String("_data"))) return false; - } m_currentFunction = prettyName.left(prettyName.size() - 5); m_currentTags.clear(); From 128995b272998e998fc8c1aacc8e4a1449bd4ac8 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 29 Oct 2015 10:14:35 +0100 Subject: [PATCH 154/200] Fix potential crash There's no need to call beginXYZ() or endXYZ() on our own as this is done by TreeModel. Change-Id: I647f280a45c5f3ebb191a8e945c423eed22d677c Reviewed-by: Niels Weber Reviewed-by: David Schulz --- plugins/autotest/testtreemodel.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 2f7366b3793..49e28c3ba35 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -631,14 +631,10 @@ void TestTreeModel::processChildren(QModelIndex &parentIndex, const TestTreeItem // handle data tags - just remove old and add them if (modifiedChild->childCount() || toBeModifiedChild->childCount()) { - beginRemoveRows(child, 0, toBeModifiedChild->childCount()); toBeModifiedChild->removeChildren(); - endRemoveRows(); const int count = modifiedChild->childCount(); - beginInsertRows(child, 0, count); for (int childRow = 0; childRow < count; ++childRow) toBeModifiedChild->appendChild(new TestTreeItem(*modifiedChild->childItem(childRow))); - endInsertRows(); } if (checkStates.contains(toBeModifiedChild->name())) { From fa9912f3ad774bf71230ce9239b1e548c572c61a Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 29 Oct 2015 12:16:30 +0100 Subject: [PATCH 155/200] Don't display checkboxes for data tags... ..as they can't be (un)checked at all. Might make sense later on but at the current state of data tag support they're completely useless. Change-Id: I3b2b79e1d2aa445fcd12d6794151d1833040aa76 Reviewed-by: Niels Weber --- plugins/autotest/testtreeitem.cpp | 1 + plugins/autotest/testtreemodel.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index 6c29f886e85..d25964cfb5e 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -101,6 +101,7 @@ QVariant TestTreeItem::data(int /*column*/, int role) const case ROOT: case TEST_DATAFUNCTION: case TEST_SPECIALFUNCTION: + case TEST_DATATAG: return QVariant(); case TEST_CLASS: return m_name.isEmpty() ? QVariant() : checked(); diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 49e28c3ba35..c59d69a7457 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -169,6 +169,7 @@ Qt::ItemFlags TestTreeModel::flags(const QModelIndex &index) const return Qt::ItemIsEnabled; case TestTreeItem::TEST_DATAFUNCTION: case TestTreeItem::TEST_SPECIALFUNCTION: + case TestTreeItem::TEST_DATATAG: default: return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } From 1b97b5e4d3757e5e5ca85032c133009dea9de945 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 8 Sep 2015 13:58:07 +0200 Subject: [PATCH 156/200] Fix data tag support for split header and source If data functions where defined inside the source file when having source and header split they were simply ignored. Change-Id: I6d32d3c721f656797a78d3ea740c102d6b93ec88 Reviewed-by: Niels Weber Reviewed-by: David Schulz --- plugins/autotest/testcodeparser.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index b5451aef8eb..975b92de922 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -480,8 +480,12 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr document) visitor.accept(declaringDoc->globalNamespace()); const QMap testFunctions = visitor.privateSlots(); - const QMap dataTags = + QMap dataTags = checkForDataTags(declaringDoc->fileName(), testFunctions); + + if (declaringDoc->fileName() != document->fileName()) + dataTags.unite(checkForDataTags(document->fileName(), testFunctions)); + TestTreeItem *item = constructTestTreeItem(declaringDoc->fileName(), QString(), testCaseName, line, column, testFunctions, dataTags); From 28fc8c02b36875dae31c1baa5d77a6d4b08fd0c1 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 2 Nov 2015 11:06:19 +0100 Subject: [PATCH 157/200] Add plugin unit test for data tags Change-Id: I765989cd18c3aff0b8bbc81e4e303e9354e327b7 Reviewed-by: David Schulz Reviewed-by: Niels Weber --- plugins/autotest/autotestunittests.cpp | 21 +++++++++++++++------ plugins/autotest/testtreemodel.cpp | 11 +++++++++++ plugins/autotest/testtreemodel.h | 1 + 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/plugins/autotest/autotestunittests.cpp b/plugins/autotest/autotestunittests.cpp index 8878f754183..1a8097c48ca 100644 --- a/plugins/autotest/autotestunittests.cpp +++ b/plugins/autotest/autotestunittests.cpp @@ -79,6 +79,7 @@ void AutoTestUnitTests::testCodeParser() QFETCH(int, expectedAutoTestsCount); QFETCH(int, expectedNamedQuickTestsCount); QFETCH(int, expectedUnnamedQuickTestsCount); + QFETCH(int, expectedDataTagsCount); NavigationWidget *navigation = NavigationWidget::instance(); navigation->activateSubWidget(Constants::AUTOTEST_ID); @@ -96,6 +97,7 @@ void AutoTestUnitTests::testCodeParser() QCOMPARE(m_model->autoTestsCount(), expectedAutoTestsCount); QCOMPARE(m_model->namedQuickTestsCount(), expectedNamedQuickTestsCount); QCOMPARE(m_model->unnamedQuickTestsCount(), expectedUnnamedQuickTestsCount); + QCOMPARE(m_model->dataTagsCount(), expectedDataTagsCount); QCOMPARE(m_model->parser()->autoTestsCount(), expectedAutoTestsCount); QCOMPARE(m_model->parser()->namedQuickTestsCount(), expectedNamedQuickTestsCount); @@ -109,20 +111,21 @@ void AutoTestUnitTests::testCodeParser_data() QTest::addColumn("expectedAutoTestsCount"); QTest::addColumn("expectedNamedQuickTestsCount"); QTest::addColumn("expectedUnnamedQuickTestsCount"); + QTest::addColumn("expectedDataTagsCount"); QTest::newRow("plainAutoTest") << QString(m_tmpDir->path() + QLatin1String("/plain/plain.pro")) - << 1 << 0 << 0; + << 1 << 0 << 0 << 0; QTest::newRow("mixedAutoTestAndQuickTests") << QString(m_tmpDir->path() + QLatin1String("/mixed_atp/mixed_atp.pro")) - << 3 << 5 << 3; + << 3 << 5 << 3 << 8; QTest::newRow("plainAutoTestQbs") << QString(m_tmpDir->path() + QLatin1String("/plain/plain.qbs")) - << 1 << 0 << 0; - QTest::newRow("mixedAuotTestAndQuickTestsQbs") + << 1 << 0 << 0 << 0; + QTest::newRow("mixedAutoTestAndQuickTestsQbs") << QString(m_tmpDir->path() + QLatin1String("/mixed_atp/mixed_atp.qbs")) - << 3 << 5 << 3; + << 3 << 5 << 3 << 8; } void AutoTestUnitTests::testCodeParserSwitchStartup() @@ -131,6 +134,7 @@ void AutoTestUnitTests::testCodeParserSwitchStartup() QFETCH(QList, expectedAutoTestsCount); QFETCH(QList, expectedNamedQuickTestsCount); QFETCH(QList, expectedUnnamedQuickTestsCount); + QFETCH(QList, expectedDataTagsCount); NavigationWidget *navigation = NavigationWidget::instance(); navigation->activateSubWidget(Constants::AUTOTEST_ID); @@ -149,6 +153,8 @@ void AutoTestUnitTests::testCodeParserSwitchStartup() m_isQt4 ? 0 : expectedNamedQuickTestsCount.at(i)); QCOMPARE(m_model->unnamedQuickTestsCount(), m_isQt4 ? 0 : expectedUnnamedQuickTestsCount.at(i)); + QCOMPARE(m_model->dataTagsCount(), + expectedDataTagsCount.at(i)); QCOMPARE(m_model->parser()->autoTestsCount(), expectedAutoTestsCount.at(i)); QCOMPARE(m_model->parser()->namedQuickTestsCount(), @@ -164,6 +170,7 @@ void AutoTestUnitTests::testCodeParserSwitchStartup_data() QTest::addColumn >("expectedAutoTestsCount"); QTest::addColumn >("expectedNamedQuickTestsCount"); QTest::addColumn >("expectedUnnamedQuickTestsCount"); + QTest::addColumn >("expectedDataTagsCount"); QStringList projects = QStringList() << QString(m_tmpDir->path() + QLatin1String("/plain/plain.pro")) @@ -174,9 +181,11 @@ void AutoTestUnitTests::testCodeParserSwitchStartup_data() QList expectedAutoTests = QList() << 1 << 3 << 1 << 3; QList expectedNamedQuickTests = QList() << 0 << 5 << 0 << 5; QList expectedUnnamedQuickTests = QList() << 0 << 3 << 0 << 3; + QList expectedDataTagsCount = QList() << 0 << 8 << 0 << 8; QTest::newRow("loadMultipleProjects") - << projects << expectedAutoTests << expectedNamedQuickTests << expectedUnnamedQuickTests; + << projects << expectedAutoTests << expectedNamedQuickTests + << expectedUnnamedQuickTests << expectedDataTagsCount; } } // namespace Internal diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index c59d69a7457..7271ccfd17b 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -670,6 +670,17 @@ int TestTreeModel::unnamedQuickTestsCount() const return unnamed->childCount(); return 0; } + +int TestTreeModel::dataTagsCount() const +{ + int dataTagCount = 0; + foreach (Utils::TreeItem *item, m_autoTestRootItem->children()) { + TestTreeItem *classItem = static_cast(item); + foreach (Utils::TreeItem *functionItem, classItem->children()) + dataTagCount += functionItem->childCount(); + } + return dataTagCount; +} #endif /***************************** Sort/Filter Model **********************************/ diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 5c51648ed50..fe0a8d702b7 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -67,6 +67,7 @@ public: int autoTestsCount() const; int namedQuickTestsCount() const; int unnamedQuickTestsCount() const; + int dataTagsCount() const; #endif signals: From 495e1a2d24040a5472bd484262f8f5810c64b1d1 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Tue, 24 Nov 2015 15:46:51 +0100 Subject: [PATCH 158/200] Use the new Utils::Icon class and update some icons Change-Id: Iff68d059e32507a688abe6f859f029d306b2b6a5 Reviewed-by: Christian Kandeler Reviewed-by: Eike Ziller --- plugins/autotest/autotest.pro | 3 +- plugins/autotest/autotest.qbs | 1 + plugins/autotest/autotest.qrc | 11 +++-- plugins/autotest/autotesticons.h | 43 ++++++++++++++++++ plugins/autotest/images/collapse.png | Bin 205 -> 176 bytes plugins/autotest/images/collapse@2x.png | Bin 0 -> 190 bytes plugins/autotest/images/expand.png | Bin 216 -> 174 bytes plugins/autotest/images/expand@2x.png | Bin 0 -> 190 bytes plugins/autotest/images/leafsort.png | Bin 415 -> 178 bytes plugins/autotest/images/leafsort@2x.png | Bin 0 -> 362 bytes plugins/autotest/images/run.png | Bin 509 -> 0 bytes plugins/autotest/images/runselected.png | Bin 709 -> 0 bytes plugins/autotest/images/runselected_boxes.png | Bin 0 -> 99 bytes .../autotest/images/runselected_boxes@2x.png | Bin 0 -> 104 bytes .../autotest/images/runselected_tickmarks.png | Bin 0 -> 151 bytes .../images/runselected_tickmarks@2x.png | Bin 0 -> 162 bytes plugins/autotest/images/sort.png | Bin 233 -> 139 bytes plugins/autotest/images/sort@2x.png | Bin 0 -> 205 bytes plugins/autotest/images/stop.png | Bin 314 -> 0 bytes plugins/autotest/testnavigationwidget.cpp | 14 +++--- plugins/autotest/testresultspane.cpp | 16 +++++-- 21 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 plugins/autotest/autotesticons.h create mode 100644 plugins/autotest/images/collapse@2x.png create mode 100644 plugins/autotest/images/expand@2x.png create mode 100644 plugins/autotest/images/leafsort@2x.png delete mode 100644 plugins/autotest/images/run.png delete mode 100644 plugins/autotest/images/runselected.png create mode 100644 plugins/autotest/images/runselected_boxes.png create mode 100644 plugins/autotest/images/runselected_boxes@2x.png create mode 100644 plugins/autotest/images/runselected_tickmarks.png create mode 100644 plugins/autotest/images/runselected_tickmarks@2x.png create mode 100644 plugins/autotest/images/sort@2x.png delete mode 100644 plugins/autotest/images/stop.png diff --git a/plugins/autotest/autotest.pro b/plugins/autotest/autotest.pro index 4022cb43990..1a411d34908 100644 --- a/plugins/autotest/autotest.pro +++ b/plugins/autotest/autotest.pro @@ -49,7 +49,8 @@ HEADERS += \ testsettings.h \ testsettingspage.h \ testnavigationwidget.h \ - testxmloutputreader.h + testxmloutputreader.h \ + autotesticons.h RESOURCES += \ autotest.qrc diff --git a/plugins/autotest/autotest.qbs b/plugins/autotest/autotest.qbs index f746d7fae13..704394044c7 100644 --- a/plugins/autotest/autotest.qbs +++ b/plugins/autotest/autotest.qbs @@ -30,6 +30,7 @@ QtcCommercialPlugin { files: [ "autotest.qrc", + "autotesticons.h", "autotest_global.h", "autotestconstants.h", "autotestplugin.cpp", diff --git a/plugins/autotest/autotest.qrc b/plugins/autotest/autotest.qrc index 8c70e3ae3f5..698a86950e4 100644 --- a/plugins/autotest/autotest.qrc +++ b/plugins/autotest/autotest.qrc @@ -4,9 +4,13 @@ images/class.png images/func.png images/expand.png + images/expand@2x.png images/collapse.png + images/collapse@2x.png images/sort.png + images/sort@2x.png images/leafsort.png + images/leafsort@2x.png images/debug.png images/fail.png images/fatal.png @@ -18,9 +22,10 @@ images/blacklisted_fail.png images/blacklisted_pass.png images/benchmark.png - images/run.png - images/runselected.png - images/stop.png + images/runselected_boxes.png + images/runselected_boxes@2x.png + images/runselected_tickmarks.png + images/runselected_tickmarks@2x.png images/data.png diff --git a/plugins/autotest/autotesticons.h b/plugins/autotest/autotesticons.h new file mode 100644 index 00000000000..8454b95f405 --- /dev/null +++ b/plugins/autotest/autotesticons.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#ifndef AUTOTESTICONS_H +#define AUTOTESTICONS_H + +#include + +namespace Autotest { +namespace Icons { + +const Utils::Icon EXPAND({ + {QLatin1String(":/images/expand.png"), Utils::Theme::IconsBaseColor}}); +const Utils::Icon COLLAPSE({ + {QLatin1String(":/images/collapse.png"), Utils::Theme::IconsBaseColor}}); +const Utils::Icon SORT_ALPHABETICALLY({ + {QLatin1String(":/images/sort.png"), Utils::Theme::IconsBaseColor}}); +const Utils::Icon SORT_NATURALLY({ + {QLatin1String(":/images/leafsort.png"), Utils::Theme::IconsBaseColor}}); +const Utils::Icon RUN_SELECTED_OVERLAY({ + {QLatin1String(":/images/runselected_boxes.png"), Utils::Theme::BackgroundColorDark}, + {QLatin1String(":/images/runselected_tickmarks.png"), Utils::Theme::IconsBaseColor}}); + +} // namespace Icons +} // namespace Autotest + +#endif // AUTOTESTICONS_H diff --git a/plugins/autotest/images/collapse.png b/plugins/autotest/images/collapse.png index d6da22a5b86804591b12af7205efb0c2d5b08ea6..c8dc840a61e7080a7587a081f6c16078406654e0 100644 GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd7G?$phPQVgfdsSyd_r6q7#P^t*qof4oSmIr zTwGjTU0YgOT3cJ&+uQHozyILDgC9SB{QUXz|NsA?G5x*_3=EE*E{-7_(aAfwS$Td) znDa_X>~-kzwk>}@r9ndc{Jp)q1&{1t2q|DZv*W;l0!CMsbo?U=@% bGDe1UkCbS~#fFIt3=9mOu6{1-oD!Mk44ofy`glX=O&z`&N| z?e4a1@p0td-tRLqan6F$jH88rfulD!<|Ns9>7CgMYJ^z1tk^+;!(hk;RJBpw4 zwe1cG36YSLkdP?YrKw~z%fwvpskK|uAx?&<(1g(0E&Wvt3=9mOu6{1-oD!M>-n?C@N4-7Ls_T(cV1I& qq-7oTF_=B4BH_{=zxKB1eGClioXW26kC1!>a+s&9pUXO@geCx(GeWrl literal 0 HcmV?d00001 diff --git a/plugins/autotest/images/expand.png b/plugins/autotest/images/expand.png index a859960ea8d77ebe801a90eb7b572437b3ab54fa..a8b3f4a486e4305952443be5f4c651cee37d9a26 100644 GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd7G?$phPQVgfdsSyd_r6q7#P^t*qof4oSmIr zTwGjTU0YgOT3cJ&+uQHozyILDgC9SB{QUXz|NsA?G5x*_3=H<3E{-7_(aAfwS$Td) znDa_X>~-kzwk>}@r9ndceB6%Rf=6~Rv?&~8WozTsP%1E;p8f8gC#zwerICT#!>!y5 ZkrgTGTSR}FGB7YOc)I$ztaD0e0syw#JIDY4 literal 216 zcmeAS@N?(olHy`uVBq!ia0y~yVBiE{4mJh`h6fYb1Q-|?7>k44ofy`glX=O&z`&N| z?e4z?Djv}DuUP*w&{ zuY3lBz4~|O?p(t^Ek%K=A#K^adtbQh?mE6m`oGjWzH8a#6Z7?YimdIQtZ3|IU|?YI MboFyt=akR{0H>-n?hrY#ju)`spwZZd`x8d>hfg4yMzL#;0+TSYadz9xN)1$Y?@ zzG=(;>uWi4lvH-VT|cR^Q^4ZHiN$k2%RKusfB9;c>k7Y@US07(QL5~GqBsMCr|tdP TBhlAEj$!b0^>bP0l+XkKMLtcG delta 400 zcmdnQIG=ffWIY=L1B3kM|A`C?jA@=Ojv*GkODFI3W_A=fdOzj8lHn001+F@gwAB-$ zbS`)HMl2CzS(~%wEmKp{+TN)w(f^q@2669}@#s2HC>nLW|OJ#W5mlXz$6#YWw- z`?K%!8TU*$Qmdd)0yb`eA+y9L7#y3zu&2J`gjK`T9WVY&dHTEV zSmB)HN$d=p7)~*4=~&~pX2HdbjHMxSpO~GTY``PF_1biXdmeheYYs$JD=Ya&y{=^l z{NpUhc|7bv-7xJVz2LAef@PL!)%6kkN-`y6_^-2NpuolgLZbV;!K}; z%mzDS@;D5NxRgHKx~|ipoc-2$f2H-`?fUN%#B1)K*I3HMVA5dBuzhXV>KGldx8Ijc zWJo?E*U;5r;%S$?mfz6k&_zcfmB6)Ov6DIv{@w2WZ}++R&wp*Z+B;RTn}LCWlfl!~ K&t;ucLK6UElCjYM diff --git a/plugins/autotest/images/leafsort@2x.png b/plugins/autotest/images/leafsort@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b74a94fc1678428d85426954b8f2255c98a38841 GIT binary patch literal 362 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(2ALr)jS5R21$FYnhrQYdr$ z@#|4q%k=upf2TeyiE6mhiu&sPbDnsJ9I#4HS1i*q`i-J z_5FVO?zfT5<=TDf%wJ;%j{kuZYwz$a5Lvf4b-7C94YdhU$D{l_gl7CxwC(!8XAkFTmb8~uddrpam@O85 ze5ft9!n8rtY~N#TU$zITiZ5d)<-J(VV);t-X5&Wnms0{%H%NPUxtEA6F%9GKXX!l2 zw@G#7d}ii|RKLJKnJ*`7+rwxRHE&11?aM{29UB8Dml)Sba_*e5vG>7@PZft%lhyAp zEBsm2{;WLy%u?Ie3xA$kdG+M$vyKuwidX$*clcd(@TXoBGxzVC^>%yX8~h`(YV+BO R3+8|V(bLt>Wt~$(699iNpGp7# literal 0 HcmV?d00001 diff --git a/plugins/autotest/images/run.png b/plugins/autotest/images/run.png deleted file mode 100644 index e302fe33e0084b483b5e9b7c731f5d1c85e96d71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 509 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7k9fK`hFJ72oqXOqBv9t) zd091yc?*meCU_-nJyBq)m!!faBGM%0ERcJPW$WrNN5|PqLL2|GUvrv%P3I3|*Me@v zo{ZPalrrw@SyB1^Y{mVU`+L93id*>_FIyqIqh@E#`=1|d3-&ju{B!4I5OCU(zCKpt z3xCOcYdwXX;WPKwTedIJh}&yw5k2Q_gY4b|rRL^|**Ry}^ z3##%pvg1|IkVe)?R8#LF26qn=uN&Sqek#IvR=R`#9i zgtO0f@iZ#@YrT*+VN1P#!vT$BZikGyF6OO|d>uVIf@j&rn7Il&?@BQ;F1EN*w11<> z)eraL9Rls1@_${s^)I`C)ZIVJvke12*gpz>t7;#@_4}kQgM$gf>Z?N6R^@LDsdT&~ zlaj~S@MD$Av!=?Lu>PN_cWlnwD43|g`Q%pE#Nu_=-@Dr`+IP;0gTe~DWM4f{&?&L diff --git a/plugins/autotest/images/runselected.png b/plugins/autotest/images/runselected.png deleted file mode 100644 index 328974062effb73ad838265bb8baaf0839525033..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 709 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!todOTemLo9liPLB7O94K*Y z{$m;4%}c+ee?FfQ5y;ZzGGUS+XRn)Y(<0qho4WI6U2whIBfzrQ(X(l~Xs1h^N0Q)G zjCgF9EDXnH z?0lQ@*|^TKI9u_P`mWGK1%VmcZsts7IPiIoqd?1w%P;rzn6g?|x7&Wa_dGml?({wz zrT|};8+)EVe||JZ&)wVGJ7xRrmHYSGd%3W(GHjW%?$ScN>c6eRTkplXXUm>VpC#vR zuVbg8B+Jm&*0!znaN?09!!2939C%v9$q=xS?ZVGJKAfh_qNf%e%(cE#wf^e<|IZG- zob_#1H^YUych|N!DMqXfE0AGde9=R-VTn?p(@BMeX%hleK7>|=mEOITxa+b>(w=SK zOSRNDUA!3R&6?op;m3T?41o*xi3()gb#_{&%k3{^f=%PdzY|^bB?Ln(RHliGk$^D@(Y$f#x@% ziD8TkE-p=KuQ^?#q!okj@i1sHHtl2b{O#y+D~(@a1*`CMQBKKN&DVDgS1*X50p5zopr E04cQ`_y7O^ literal 0 HcmV?d00001 diff --git a/plugins/autotest/images/runselected_tickmarks.png b/plugins/autotest/images/runselected_tickmarks.png new file mode 100644 index 0000000000000000000000000000000000000000..6296f8748da1fad940d19c9c4de130ed3e9d725d GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd7G?$phPQVgfdte8d_r7BMMbr>we|J&6A}{g z^Ygp9x)v;0uz&ylt5>gn`0(ND*RS8cef$6azxv0JBMb}-+MX_sAso@k7R;E?}E3Va77`PP?QwR^~aa=Lj3=PSj92`08YTfZZBFrFshhMH>F^7Re zh62-7-DhyXrLokg8`4X z`~FGI;RpZkKOp|Z@UzN^8%s)=x%W<4<|&ns>bWX1u!o)hJ%b;ELS`oG`O4joH-Gc` z!r=M(c@E2)jUKDkzbQ|@64|2or#b!=(~f0s%R-`j S_!$@&7(8A5T-G@yGywood{2h} diff --git a/plugins/autotest/images/sort@2x.png b/plugins/autotest/images/sort@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1a2e5d9520463a203c9dd440478118f7ee7e6f51 GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(2=DV{ElAr`&KKl~XCczT*D zkHy5OeJ;?Rae#qM_=1SRfyf}9V!QfzhZS0b8CzH%U-n>R30Ty?*Qc_8L3F}mhF7QG zwun?b+WN?lUryLTp+!+-y>hv6f$f3i50I|WYi%5qeyh$~rd+9!AH(~)@z0twcNtScH8Ffkac4$fJrcc=yAPES`qmvv4F FO#q>eL+$_o literal 0 HcmV?d00001 diff --git a/plugins/autotest/images/stop.png b/plugins/autotest/images/stop.png deleted file mode 100644 index 1063d089985794a49542c61f78e8d8514f7f9607..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 314 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7BuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztFx>HUaSW-rwPdm*SF?eDtNPK+QMXFZUrb#px48N% zo19~aK#Yc{j@V?i%S%j@%vN?WpKSSXfBqQ<4y8lW3ce)zpKx7vnCseZCArSJMw0`Z zUrSB3IH~2gkN;AGMRC&H%2?*}#SdH=n=aiKvs)y% #include #include +#include #include #include #include @@ -149,7 +151,7 @@ QList TestNavigationWidget::createToolButtons() QList list; m_filterButton = new QToolButton(m_view); - m_filterButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_FILTER))); + m_filterButton->setIcon(Core::Icons::FILTER.icon()); m_filterButton->setToolTip(tr("Filter Test Tree")); m_filterButton->setProperty("noArrow", true); m_filterButton->setAutoRaise(true); @@ -161,15 +163,15 @@ QList TestNavigationWidget::createToolButtons() m_sortAlphabetically = true; m_sort = new QToolButton(this); - m_sort->setIcon((QIcon(QLatin1String(":/images/leafsort.png")))); + m_sort->setIcon(Icons::SORT_NATURALLY.icon()); m_sort->setToolTip(tr("Sort Naturally")); QToolButton *expand = new QToolButton(this); - expand->setIcon(QIcon(QLatin1String(":/images/expand.png"))); + expand->setIcon(Icons::EXPAND.icon()); expand->setToolTip(tr("Expand All")); QToolButton *collapse = new QToolButton(this); - collapse->setIcon(QIcon(QLatin1String(":/images/collapse.png"))); + collapse->setIcon(Icons::COLLAPSE.icon()); collapse->setToolTip(tr("Collapse All")); connect(expand, &QToolButton::clicked, m_view, &TestTreeView::expandAll); @@ -193,11 +195,11 @@ void TestNavigationWidget::onItemActivated(const QModelIndex &index) void TestNavigationWidget::onSortClicked() { if (m_sortAlphabetically) { - m_sort->setIcon((QIcon(QLatin1String(":/images/sort.png")))); + m_sort->setIcon(Icons::SORT_ALPHABETICALLY.icon()); m_sort->setToolTip(tr("Sort Alphabetically")); m_sortFilterModel->setSortMode(TestTreeSortFilterModel::Naturally); } else { - m_sort->setIcon((QIcon(QLatin1String(":/images/leafsort.png")))); + m_sort->setIcon(Icons::SORT_NATURALLY.icon()); m_sort->setToolTip(tr("Sort Naturally")); m_sortFilterModel->setSortMode(TestTreeSortFilterModel::Alphabetically); } diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index abc91dfb66e..253dc6685ec 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -18,6 +18,7 @@ ****************************************************************************/ #include "autotestplugin.h" +#include "autotesticons.h" #include "testresultspane.h" #include "testresultmodel.h" #include "testresultdelegate.h" @@ -26,10 +27,13 @@ #include "testtreemodel.h" #include +#include #include #include #include +#include + #include #include @@ -127,7 +131,7 @@ TestResultsPane::TestResultsPane(QObject *parent) : void TestResultsPane::createToolButtons() { m_expandCollapse = new QToolButton(m_treeView); - m_expandCollapse->setIcon(QIcon(QLatin1String(":/find/images/expand.png"))); + m_expandCollapse->setIcon(Core::Icons::EXPAND.icon()); m_expandCollapse->setToolTip(tr("Expand All")); m_expandCollapse->setCheckable(true); m_expandCollapse->setChecked(false); @@ -139,25 +143,27 @@ void TestResultsPane::createToolButtons() }); m_runAll = new QToolButton(m_treeView); - m_runAll->setIcon(QIcon(QLatin1String(":/images/run.png"))); + m_runAll->setIcon(ProjectExplorer::Icons::RUN_SMALL.icon()); m_runAll->setToolTip(tr("Run All Tests")); m_runAll->setEnabled(false); connect(m_runAll, &QToolButton::clicked, this, &TestResultsPane::onRunAllTriggered); m_runSelected = new QToolButton(m_treeView); - m_runSelected->setIcon(QIcon(QLatin1String(":/images/runselected.png"))); + Utils::Icon runSelectedIcon = ProjectExplorer::Icons::RUN_SMALL; + runSelectedIcon.append(Icons::RUN_SELECTED_OVERLAY); + m_runSelected->setIcon(runSelectedIcon.icon()); m_runSelected->setToolTip(tr("Run Selected Tests")); m_runSelected->setEnabled(false); connect(m_runSelected, &QToolButton::clicked, this, &TestResultsPane::onRunSelectedTriggered); m_stopTestRun = new QToolButton(m_treeView); - m_stopTestRun->setIcon(QIcon(QLatin1String(":/images/stop.png"))); + m_stopTestRun->setIcon(ProjectExplorer::Icons::STOP_SMALL.icon()); m_stopTestRun->setToolTip(tr("Stop Test Run")); m_stopTestRun->setEnabled(false); connect(m_stopTestRun, &QToolButton::clicked, TestRunner::instance(), &TestRunner::requestStopTestRun); m_filterButton = new QToolButton(m_treeView); - m_filterButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_FILTER))); + m_filterButton->setIcon(Core::Icons::FILTER.icon()); m_filterButton->setToolTip(tr("Filter Test Results")); m_filterButton->setProperty("noArrow", true); m_filterButton->setAutoRaise(true); From 7eab6a53b17747bf706d9f42bbb13d65f9a97ef6 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 26 Nov 2015 13:41:26 +0100 Subject: [PATCH 159/200] Fix missing handling for xml tag Without this we're running into the QTC_ASSERT within the default case. ("unexpected cdatamode...") Change-Id: I75b3b1ff08ff11064042cd2a877bcfe373b46e45 Reviewed-by: Niels Weber --- plugins/autotest/testxmloutputreader.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/autotest/testxmloutputreader.cpp b/plugins/autotest/testxmloutputreader.cpp index 63fa9f92873..2f2c41b8d89 100644 --- a/plugins/autotest/testxmloutputreader.cpp +++ b/plugins/autotest/testxmloutputreader.cpp @@ -142,6 +142,7 @@ enum CDATAMode { DataTag, Description, QtVersion, + QtBuild, QTestVersion }; @@ -153,6 +154,7 @@ void TestXmlOutputReader::processOutput() QStringLiteral("Message"), QStringLiteral("BenchmarkResult"), QStringLiteral("QtVersion"), + QStringLiteral("QtBuild"), QStringLiteral("QTestVersion") }; static CDATAMode cdataMode = None; static QString className; @@ -226,6 +228,9 @@ void TestXmlOutputReader::processOutput() } else if (currentTag == QStringLiteral("QtVersion")) { result = Result::MESSAGE_INTERNAL; cdataMode = QtVersion; + } else if (currentTag == QStringLiteral("QtBuild")) { + result = Result::MESSAGE_INTERNAL; + cdataMode = QtBuild; } else if (currentTag == QStringLiteral("QTestVersion")) { result = Result::MESSAGE_INTERNAL; cdataMode = QTestVersion; @@ -249,6 +254,10 @@ void TestXmlOutputReader::processOutput() case QtVersion: description = tr("Qt version: %1").arg(text.toString()); break; + case QtBuild: + // FIXME due to string freeze this is not a tr() + description = QString::fromLatin1("Qt build: %1").arg(text.toString()); + break; case QTestVersion: description = tr("QTest version: %1").arg(text.toString()); break; From 1bfee1252f99901f92ebc660e21800a98c168ee5 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 3 Dec 2015 13:12:41 +0100 Subject: [PATCH 160/200] Fix compile with Qt5.4 Broke with 495e1a2d24040a5472bd484262f8f5810c64b1d1 - appending another QVector to an existing has been added to Qt5.5. Change-Id: I277541bfa4cae89d7807ac104f2595f315b97271 Reviewed-by: Alessandro Portale --- plugins/autotest/testresultspane.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 253dc6685ec..fa2a534736b 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -150,7 +150,8 @@ void TestResultsPane::createToolButtons() m_runSelected = new QToolButton(m_treeView); Utils::Icon runSelectedIcon = ProjectExplorer::Icons::RUN_SMALL; - runSelectedIcon.append(Icons::RUN_SELECTED_OVERLAY); + foreach (const Utils::IconMaskAndColor &maskAndColor, Icons::RUN_SELECTED_OVERLAY) + runSelectedIcon.append(maskAndColor); m_runSelected->setIcon(runSelectedIcon.icon()); m_runSelected->setToolTip(tr("Run Selected Tests")); m_runSelected->setEnabled(false); From 1a8f37db0e61155aa23746f8839c8970772d3f22 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 9 Dec 2015 07:52:15 +0100 Subject: [PATCH 161/200] Delete pointer if it is no more used... ...and postpone creation of the newItem object a bit. Change-Id: Id2322dcaae33cd902267dc73d2929db06880e20c Reviewed-by: David Schulz --- plugins/autotest/testresultmodel.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index 5a09b5670b9..3e945a656ce 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -137,7 +137,6 @@ void TestResultModel::addTestResult(TestResult *testResult, bool autoExpand) QVector topLevelItems = rootItem()->children(); int lastRow = topLevelItems.size() - 1; - TestResultItem *newItem = new TestResultItem(testResult); // we'll add the new item, so raising it's counter if (!isCurrentTestMssg) { int count = m_testResultCount.value(testResult->result(), 0); @@ -150,14 +149,16 @@ void TestResultModel::addTestResult(TestResult *testResult, bool autoExpand) if (result && result->result() == Result::MESSAGE_CURRENT_TEST) { current->updateDescription(testResult->description()); emit dataChanged(current->index(), current->index()); + delete testResult; return; } } - rootItem()->appendChild(newItem); + rootItem()->appendChild(new TestResultItem(testResult)); return; } + TestResultItem *newItem = new TestResultItem(testResult); // FIXME this might be totally wrong... we need some more unique information! for (int row = lastRow; row >= 0; --row) { TestResultItem *current = static_cast(topLevelItems.at(row)); From fb7ceae64bb443fd2e5a199816553d8c49aaec86 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 7 Dec 2015 08:26:54 +0100 Subject: [PATCH 162/200] Use Qt style for enums Change-Id: I10c1379dea467f10214772168f4c1ec3134a99ee Reviewed-by: Niels Weber --- plugins/autotest/testcodeparser.cpp | 2 +- plugins/autotest/testnavigationwidget.cpp | 10 +-- plugins/autotest/testresult.cpp | 68 ++++++++++---------- plugins/autotest/testresult.h | 40 ++++++------ plugins/autotest/testresultdelegate.cpp | 14 ++--- plugins/autotest/testresultmodel.cpp | 76 +++++++++++------------ plugins/autotest/testresultspane.cpp | 36 +++++------ plugins/autotest/testrunner.cpp | 18 +++--- plugins/autotest/testtreeitem.cpp | 44 ++++++------- plugins/autotest/testtreeitem.h | 14 ++--- plugins/autotest/testtreemodel.cpp | 36 +++++------ plugins/autotest/testvisitor.cpp | 16 ++--- plugins/autotest/testxmloutputreader.cpp | 20 +++--- 13 files changed, 197 insertions(+), 197 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 975b92de922..6f32e8dc582 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -389,7 +389,7 @@ static TestTreeItem *constructTestTreeItem(const QString &fileName, const QMap &functions, const QMap dataTags = QMap()) { - TestTreeItem *treeItem = new TestTreeItem(testCaseName, fileName, TestTreeItem::TEST_CLASS); + TestTreeItem *treeItem = new TestTreeItem(testCaseName, fileName, TestTreeItem::TestClass); treeItem->setMainFile(mainFile); // used for Quick Tests only treeItem->setLine(line); treeItem->setColumn(column); diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index 33d996c892b..e396c807ebc 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -104,9 +104,9 @@ void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event) // do not provide this menu entry for unnamed Quick Tests as it makes no sense int type = index.data(TypeRole).toInt(); const QString &unnamed = tr(Constants::UNNAMED_QUICKTESTS); - if ((type == TestTreeItem::TEST_FUNCTION && index.parent().data().toString() != unnamed) - || (type == TestTreeItem::TEST_CLASS && index.data().toString() != unnamed) - || (type == TestTreeItem::TEST_DATATAG)) { + if ((type == TestTreeItem::TestFunction && index.parent().data().toString() != unnamed) + || (type == TestTreeItem::TestClass && index.data().toString() != unnamed) + || (type == TestTreeItem::TestDataTag)) { runThisTest = new QAction(tr("Run This Test"), &menu); runThisTest->setEnabled(enabled); connect(runThisTest, &QAction::triggered, @@ -250,8 +250,8 @@ void TestNavigationWidget::onRunThisTestTriggered() return; TestTreeItem *item = static_cast(sourceIndex.internalPointer()); - if (item->type() == TestTreeItem::TEST_CLASS || item->type() == TestTreeItem::TEST_FUNCTION - || item->type() == TestTreeItem::TEST_DATATAG) { + if (item->type() == TestTreeItem::TestClass || item->type() == TestTreeItem::TestFunction + || item->type() == TestTreeItem::TestDataTag) { if (TestConfiguration *configuration = m_model->getTestConfiguration(item)) { TestRunner *runner = TestRunner::instance(); runner->setSelectedTests( {configuration} ); diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp index 293145f3e95..37929f00f4f 100644 --- a/plugins/autotest/testresult.cpp +++ b/plugins/autotest/testresult.cpp @@ -35,7 +35,7 @@ TestResult::TestResult() TestResult::TestResult(const QString &className) : m_class(className) - , m_result(Result::INVALID) + , m_result(Result::Invalid) , m_line(0) { } @@ -43,33 +43,33 @@ TestResult::TestResult(const QString &className) Result::Type TestResult::resultFromString(const QString &resultString) { if (resultString == QLatin1String("pass")) - return Result::PASS; + return Result::Pass; if (resultString == QLatin1String("fail")) - return Result::FAIL; + return Result::Fail; if (resultString == QLatin1String("xfail")) - return Result::EXPECTED_FAIL; + return Result::ExpectedFail; if (resultString == QLatin1String("xpass")) - return Result::UNEXPECTED_PASS; + return Result::UnexpectedPass; if (resultString == QLatin1String("skip")) - return Result::SKIP; + return Result::Skip; if (resultString == QLatin1String("qdebug")) - return Result::MESSAGE_DEBUG; + return Result::MessageDebug; if (resultString == QLatin1String("warn") || resultString == QLatin1String("qwarn")) - return Result::MESSAGE_WARN; + return Result::MessageWarn; if (resultString == QLatin1String("qfatal")) - return Result::MESSAGE_FATAL; + return Result::MessageFatal; if (resultString == QLatin1String("bpass")) - return Result::BLACKLISTED_PASS; + return Result::BlacklistedPass; if (resultString == QLatin1String("bfail")) - return Result::BLACKLISTED_FAIL; + return Result::BlacklistedFail; qDebug("Unexpected test result: %s", qPrintable(resultString)); - return Result::INVALID; + return Result::Invalid; } Result::Type TestResult::toResultType(int rt) { if (rt < Result::FIRST_TYPE || rt > Result::LAST_TYPE) - return Result::INVALID; + return Result::Invalid; return (Result::Type)rt; } @@ -80,27 +80,27 @@ QString TestResult::resultToString(const Result::Type type) return QString(); switch (type) { - case Result::PASS: + case Result::Pass: return QLatin1String("PASS"); - case Result::FAIL: + case Result::Fail: return QLatin1String("FAIL"); - case Result::EXPECTED_FAIL: + case Result::ExpectedFail: return QLatin1String("XFAIL"); - case Result::UNEXPECTED_PASS: + case Result::UnexpectedPass: return QLatin1String("XPASS"); - case Result::SKIP: + case Result::Skip: return QLatin1String("SKIP"); - case Result::BENCHMARK: + case Result::Benchmark: return QLatin1String("BENCH"); - case Result::MESSAGE_DEBUG: + case Result::MessageDebug: return QLatin1String("DEBUG"); - case Result::MESSAGE_WARN: + case Result::MessageWarn: return QLatin1String("WARN"); - case Result::MESSAGE_FATAL: + case Result::MessageFatal: return QLatin1String("FATAL"); - case Result::BLACKLISTED_PASS: + case Result::BlacklistedPass: return QLatin1String("BPASS"); - case Result::BLACKLISTED_FAIL: + case Result::BlacklistedFail: return QLatin1String("BFAIL"); default: return QLatin1String("UNKNOWN"); @@ -113,25 +113,25 @@ QColor TestResult::colorForType(const Result::Type type) return QColor("transparent"); switch (type) { - case Result::PASS: + case Result::Pass: return QColor("#009900"); - case Result::FAIL: + case Result::Fail: return QColor("#a00000"); - case Result::EXPECTED_FAIL: + case Result::ExpectedFail: return QColor("#00ff00"); - case Result::UNEXPECTED_PASS: + case Result::UnexpectedPass: return QColor("#ff0000"); - case Result::SKIP: + case Result::Skip: return QColor("#787878"); - case Result::BLACKLISTED_PASS: + case Result::BlacklistedPass: return QColor(0, 0, 0); - case Result::BLACKLISTED_FAIL: + case Result::BlacklistedFail: return QColor(0, 0, 0); - case Result::MESSAGE_DEBUG: + case Result::MessageDebug: return QColor("#329696"); - case Result::MESSAGE_WARN: + case Result::MessageWarn: return QColor("#d0bb00"); - case Result::MESSAGE_FATAL: + case Result::MessageFatal: return QColor("#640000"); default: return QColor("#000000"); diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index 1ad8d51a4ad..d28255aad0d 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -29,28 +29,28 @@ namespace Internal { namespace Result{ enum Type { - PASS, FIRST_TYPE = PASS, - FAIL, - EXPECTED_FAIL, - UNEXPECTED_PASS, - SKIP, - BLACKLISTED_PASS, - BLACKLISTED_FAIL, - BENCHMARK, - MESSAGE_DEBUG, - MESSAGE_WARN, - MESSAGE_FATAL, + Pass, FIRST_TYPE = Pass, + Fail, + ExpectedFail, + UnexpectedPass, + Skip, + BlacklistedPass, + BlacklistedFail, + Benchmark, + MessageDebug, + MessageWarn, + MessageFatal, - MESSAGE_INTERNAL, INTERNAL_MESSAGES_BEGIN = MESSAGE_INTERNAL, - MESSAGE_TEST_CASE_START, - MESSAGE_TEST_CASE_SUCCESS, - MESSAGE_TEST_CASE_WARN, - MESSAGE_TEST_CASE_FAIL, - MESSAGE_TEST_CASE_END, - MESSAGE_CURRENT_TEST, INTERNAL_MESSAGES_END = MESSAGE_CURRENT_TEST, + MessageInternal, INTERNAL_MESSAGES_BEGIN = MessageInternal, + MessageTestCaseStart, + MessageTestCaseSuccess, + MessageTestCaseWarn, + MessageTestCaseFail, + MessageTestCaseEnd, + MessageCurrentTest, INTERNAL_MESSAGES_END = MessageCurrentTest, - INVALID, - LAST_TYPE = INVALID + Invalid, + LAST_TYPE = Invalid }; } diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp index b123c99db9d..87559465a22 100644 --- a/plugins/autotest/testresultdelegate.cpp +++ b/plugins/autotest/testresultdelegate.cpp @@ -42,12 +42,12 @@ QString TestResultDelegate::outputString(const TestResult &testResult, bool sele const QString desc = testResult.description(); QString output; switch (testResult.result()) { - case Result::PASS: - case Result::FAIL: - case Result::EXPECTED_FAIL: - case Result::UNEXPECTED_PASS: - case Result::BLACKLISTED_FAIL: - case Result::BLACKLISTED_PASS: + case Result::Pass: + case Result::Fail: + case Result::ExpectedFail: + case Result::UnexpectedPass: + case Result::BlacklistedFail: + case Result::BlacklistedPass: output = testResult.className() + QLatin1String("::") + testResult.testCase(); if (!testResult.dataTag().isEmpty()) output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); @@ -55,7 +55,7 @@ QString TestResultDelegate::outputString(const TestResult &testResult, bool sele output.append(QLatin1Char('\n')).append(desc); } break; - case Result::BENCHMARK: + case Result::Benchmark: output = testResult.className() + QLatin1String("::") + testResult.testCase(); if (!testResult.dataTag().isEmpty()) output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index 5a09b5670b9..ecaa96a3864 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -52,14 +52,14 @@ static QIcon testResultIcon(Result::Type result) { QIcon(QLatin1String(":/images/fatal.png")), }; // provide an icon for unknown?? - if (result < 0 || result >= Result::MESSAGE_INTERNAL) { + if (result < 0 || result >= Result::MessageInternal) { switch (result) { - case Result::MESSAGE_TEST_CASE_SUCCESS: - return icons[Result::PASS]; - case Result::MESSAGE_TEST_CASE_FAIL: - return icons[Result::FAIL]; - case Result::MESSAGE_TEST_CASE_WARN: - return icons[Result::MESSAGE_WARN]; + case Result::MessageTestCaseSuccess: + return icons[Result::Pass]; + case Result::MessageTestCaseFail: + return icons[Result::Fail]; + case Result::MessageTestCaseWarn: + return icons[Result::MessageWarn]; default: return QIcon(); } @@ -84,25 +84,25 @@ void TestResultItem::updateDescription(const QString &description) void TestResultItem::updateResult() { - if (m_testResult->result() != Result::MESSAGE_TEST_CASE_START) + if (m_testResult->result() != Result::MessageTestCaseStart) return; - Result::Type newResult = Result::MESSAGE_TEST_CASE_SUCCESS; + Result::Type newResult = Result::MessageTestCaseSuccess; foreach (Utils::TreeItem *child, children()) { const TestResult *current = static_cast(child)->testResult(); if (current) { switch (current->result()) { - case Result::FAIL: - case Result::MESSAGE_FATAL: - case Result::UNEXPECTED_PASS: - m_testResult->setResult(Result::MESSAGE_TEST_CASE_FAIL); + case Result::Fail: + case Result::MessageFatal: + case Result::UnexpectedPass: + m_testResult->setResult(Result::MessageTestCaseFail); return; - case Result::EXPECTED_FAIL: - case Result::MESSAGE_WARN: - case Result::SKIP: - case Result::BLACKLISTED_FAIL: - case Result::BLACKLISTED_PASS: - newResult = Result::MESSAGE_TEST_CASE_WARN; + case Result::ExpectedFail: + case Result::MessageWarn: + case Result::Skip: + case Result::BlacklistedFail: + case Result::BlacklistedPass: + newResult = Result::MessageTestCaseWarn; break; default: {} } @@ -133,7 +133,7 @@ QVariant TestResultModel::data(const QModelIndex &idx, int role) const void TestResultModel::addTestResult(TestResult *testResult, bool autoExpand) { - const bool isCurrentTestMssg = testResult->result() == Result::MESSAGE_CURRENT_TEST; + const bool isCurrentTestMssg = testResult->result() == Result::MessageCurrentTest; QVector topLevelItems = rootItem()->children(); int lastRow = topLevelItems.size() - 1; @@ -143,11 +143,11 @@ void TestResultModel::addTestResult(TestResult *testResult, bool autoExpand) int count = m_testResultCount.value(testResult->result(), 0); m_testResultCount.insert(testResult->result(), ++count); } else { - // MESSAGE_CURRENT_TEST should always be the last top level item + // MessageCurrentTest should always be the last top level item if (lastRow >= 0) { TestResultItem *current = static_cast(topLevelItems.at(lastRow)); const TestResult *result = current->testResult(); - if (result && result->result() == Result::MESSAGE_CURRENT_TEST) { + if (result && result->result() == Result::MessageCurrentTest) { current->updateDescription(testResult->description()); emit dataChanged(current->index(), current->index()); return; @@ -166,18 +166,18 @@ void TestResultModel::addTestResult(TestResult *testResult, bool autoExpand) current->appendChild(newItem); if (autoExpand) current->expand(); - if (testResult->result() == Result::MESSAGE_TEST_CASE_END) { + if (testResult->result() == Result::MessageTestCaseEnd) { current->updateResult(); emit dataChanged(current->index(), current->index()); } return; } } - // if we have a MESSAGE_CURRENT_TEST present, add the new top level item before it + // if we have a MessageCurrentTest present, add the new top level item before it if (lastRow >= 0) { TestResultItem *current = static_cast(topLevelItems.at(lastRow)); const TestResult *result = current->testResult(); - if (result && result->result() == Result::MESSAGE_CURRENT_TEST) { + if (result && result->result() == Result::MessageCurrentTest) { rootItem()->insertChild(current->index().row(), newItem); return; } @@ -191,7 +191,7 @@ void TestResultModel::removeCurrentTestMessage() QVector topLevelItems = rootItem()->children(); for (int row = topLevelItems.size() - 1; row >= 0; --row) { TestResultItem *current = static_cast(topLevelItems.at(row)); - if (current->testResult()->result() == Result::MESSAGE_CURRENT_TEST) { + if (current->testResult()->result() == Result::MessageCurrentTest) { delete takeItem(current); break; } @@ -272,14 +272,14 @@ TestResultFilterModel::TestResultFilterModel(TestResultModel *sourceModel, QObje void TestResultFilterModel::enableAllResultTypes() { - m_enabled << Result::PASS << Result::FAIL << Result::EXPECTED_FAIL - << Result::UNEXPECTED_PASS << Result::SKIP << Result::MESSAGE_DEBUG - << Result::MESSAGE_WARN << Result::MESSAGE_INTERNAL - << Result::MESSAGE_FATAL << Result::INVALID << Result::BLACKLISTED_PASS - << Result::BLACKLISTED_FAIL << Result::BENCHMARK - << Result::MESSAGE_CURRENT_TEST << Result::MESSAGE_TEST_CASE_START - << Result::MESSAGE_TEST_CASE_SUCCESS << Result::MESSAGE_TEST_CASE_WARN - << Result::MESSAGE_TEST_CASE_FAIL << Result::MESSAGE_TEST_CASE_END; + m_enabled << Result::Pass << Result::Fail << Result::ExpectedFail + << Result::UnexpectedPass << Result::Skip << Result::MessageDebug + << Result::MessageWarn << Result::MessageInternal + << Result::MessageFatal << Result::Invalid << Result::BlacklistedPass + << Result::BlacklistedFail << Result::Benchmark + << Result::MessageCurrentTest << Result::MessageTestCaseStart + << Result::MessageTestCaseSuccess << Result::MessageTestCaseWarn + << Result::MessageTestCaseFail << Result::MessageTestCaseEnd; invalidateFilter(); } @@ -287,12 +287,12 @@ void TestResultFilterModel::toggleTestResultType(Result::Type type) { if (m_enabled.contains(type)) { m_enabled.remove(type); - if (type == Result::MESSAGE_INTERNAL) - m_enabled.remove(Result::MESSAGE_TEST_CASE_END); + if (type == Result::MessageInternal) + m_enabled.remove(Result::MessageTestCaseEnd); } else { m_enabled.insert(type); - if (type == Result::MESSAGE_INTERNAL) - m_enabled.insert(Result::MESSAGE_TEST_CASE_END); + if (type == Result::MessageInternal) + m_enabled.insert(Result::MessageTestCaseEnd); } invalidateFilter(); } diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index fa2a534736b..acd60274788 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -394,23 +394,23 @@ void TestResultsPane::initializeFilterMenu() const bool omitIntern = AutotestPlugin::instance()->settings()->omitInternalMssg; // FilterModel has all messages enabled by default if (omitIntern) - m_filterModel->toggleTestResultType(Result::MESSAGE_INTERNAL); + m_filterModel->toggleTestResultType(Result::MessageInternal); QMap textAndType; - textAndType.insert(Result::PASS, tr("Pass")); - textAndType.insert(Result::FAIL, tr("Fail")); - textAndType.insert(Result::EXPECTED_FAIL, tr("Expected Fail")); - textAndType.insert(Result::UNEXPECTED_PASS, tr("Unexpected Pass")); - textAndType.insert(Result::SKIP, tr("Skip")); - textAndType.insert(Result::BENCHMARK, tr("Benchmarks")); - textAndType.insert(Result::MESSAGE_DEBUG, tr("Debug Messages")); - textAndType.insert(Result::MESSAGE_WARN, tr("Warning Messages")); - textAndType.insert(Result::MESSAGE_INTERNAL, tr("Internal Messages")); + textAndType.insert(Result::Pass, tr("Pass")); + textAndType.insert(Result::Fail, tr("Fail")); + textAndType.insert(Result::ExpectedFail, tr("Expected Fail")); + textAndType.insert(Result::UnexpectedPass, tr("Unexpected Pass")); + textAndType.insert(Result::Skip, tr("Skip")); + textAndType.insert(Result::Benchmark, tr("Benchmarks")); + textAndType.insert(Result::MessageDebug, tr("Debug Messages")); + textAndType.insert(Result::MessageWarn, tr("Warning Messages")); + textAndType.insert(Result::MessageInternal, tr("Internal Messages")); foreach (Result::Type result, textAndType.keys()) { QAction *action = new QAction(m_filterMenu); action->setText(textAndType.value(result)); action->setCheckable(true); - action->setChecked(result != Result::MESSAGE_INTERNAL || !omitIntern); + action->setChecked(result != Result::MessageInternal || !omitIntern); action->setData(result); m_filterMenu->addAction(action); } @@ -425,22 +425,22 @@ void TestResultsPane::initializeFilterMenu() void TestResultsPane::updateSummaryLabel() { QString labelText = QString::fromLatin1("

Test summary:   %1 %2, %3 %4") - .arg(QString::number(m_model->resultTypeCount(Result::PASS)), tr("passes"), - QString::number(m_model->resultTypeCount(Result::FAIL)), tr("fails")); - int count = m_model->resultTypeCount(Result::UNEXPECTED_PASS); + .arg(QString::number(m_model->resultTypeCount(Result::Pass)), tr("passes"), + QString::number(m_model->resultTypeCount(Result::Fail)), tr("fails")); + int count = m_model->resultTypeCount(Result::UnexpectedPass); if (count) labelText.append(QString::fromLatin1(", %1 %2") .arg(QString::number(count), tr("unexpected passes"))); - count = m_model->resultTypeCount(Result::EXPECTED_FAIL); + count = m_model->resultTypeCount(Result::ExpectedFail); if (count) labelText.append(QString::fromLatin1(", %1 %2") .arg(QString::number(count), tr("expected fails"))); - count = m_model->resultTypeCount(Result::MESSAGE_FATAL); + count = m_model->resultTypeCount(Result::MessageFatal); if (count) labelText.append(QString::fromLatin1(", %1 %2") .arg(QString::number(count), tr("fatals"))); - count = m_model->resultTypeCount(Result::BLACKLISTED_FAIL) - + m_model->resultTypeCount(Result::BLACKLISTED_PASS); + count = m_model->resultTypeCount(Result::BlacklistedFail) + + m_model->resultTypeCount(Result::BlacklistedPass); if (count) labelText.append(QString::fromLatin1(", %1 %2") .arg(QString::number(count), tr("blacklisted"))); diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index ea26b0e75f0..aef4b53a9f2 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -114,7 +114,7 @@ void performTestRun(QFutureInterface &futureInterface, if (config->project()) { testCaseCount += config->testCaseCount(); } else { - emitTestResultCreated(new FaultyTestResult(Result::MESSAGE_WARN, + emitTestResultCreated(new FaultyTestResult(Result::MessageWarn, QObject::tr("Project is null for \"%1\". Removing from test run.\n" "Check the test environment.").arg(config->displayName()))); } @@ -148,7 +148,7 @@ void performTestRun(QFutureInterface &futureInterface, QProcessEnvironment environment = testConfiguration->environment().toProcessEnvironment(); QString commandFilePath = executableFilePath(testConfiguration->targetFile(), environment); if (commandFilePath.isEmpty()) { - emitTestResultCreated(new FaultyTestResult(Result::MESSAGE_FATAL, + emitTestResultCreated(new FaultyTestResult(Result::MessageFatal, QObject::tr("Could not find command \"%1\". (%2)") .arg(testConfiguration->targetFile()) .arg(testConfiguration->displayName()))); @@ -177,7 +177,7 @@ void performTestRun(QFutureInterface &futureInterface, if (futureInterface.isCanceled()) { testProcess.kill(); testProcess.waitForFinished(); - emitTestResultCreated(new FaultyTestResult(Result::MESSAGE_FATAL, + emitTestResultCreated(new FaultyTestResult(Result::MessageFatal, QObject::tr("Test run canceled by user."))); } qApp->processEvents(); @@ -188,7 +188,7 @@ void performTestRun(QFutureInterface &futureInterface, if (testProcess.state() != QProcess::NotRunning) { testProcess.kill(); testProcess.waitForFinished(); - emitTestResultCreated(new FaultyTestResult(Result::MESSAGE_FATAL, QObject::tr( + emitTestResultCreated(new FaultyTestResult(Result::MessageFatal, QObject::tr( "Test case canceled due to timeout. \nMaybe raise the timeout?"))); } } @@ -208,14 +208,14 @@ void TestRunner::prepareToRunTests() foreach (TestConfiguration *config, m_selectedTests) { if (!omitRunConfigWarnings && config->guessedConfiguration()) { - TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MESSAGE_WARN, + TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MessageWarn, tr("Project's run configuration was guessed for \"%1\".\n" "This might cause trouble during execution.").arg(config->displayName()))); } } if (m_selectedTests.empty()) { - TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MESSAGE_WARN, + TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MessageWarn, tr("No tests selected. Canceling test run."))); onFinished(); return; @@ -223,7 +223,7 @@ void TestRunner::prepareToRunTests() ProjectExplorer::Project *project = m_selectedTests.at(0)->project(); if (!project) { - TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MESSAGE_WARN, + TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MessageWarn, tr("Project is null. Canceling test run.\n" "Only desktop kits are supported. Make sure the " "currently active kit is a desktop kit."))); @@ -239,7 +239,7 @@ void TestRunner::prepareToRunTests() if (project->hasActiveBuildSettings()) { buildProject(project); } else { - TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MESSAGE_FATAL, + TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MessageFatal, tr("Project is not configured. Canceling test run."))); onFinished(); return; @@ -284,7 +284,7 @@ void TestRunner::buildFinished(bool success) if (success) { runTests(); } else { - TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MESSAGE_FATAL, + TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MessageFatal, tr("Build failed. Canceling test run."))); onFinished(); } diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index d25964cfb5e..6b4c5b4bc59 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -37,8 +37,8 @@ TestTreeItem::TestTreeItem(const QString &name, const QString &filePath, Type ty m_line(0) { switch (m_type) { - case TEST_CLASS: - case TEST_FUNCTION: + case TestClass: + case TestFunction: m_checked = Qt::Checked; break; default: @@ -82,14 +82,14 @@ QVariant TestTreeItem::data(int /*column*/, int role) const { switch (role) { case Qt::DisplayRole: - if (m_type == ROOT && childCount() == 0) + if (m_type == Root && childCount() == 0) return QString(m_name + QObject::tr(" (none)")); else if (m_name.isEmpty()) return QObject::tr(Constants::UNNAMED_QUICKTESTS); else return m_name; case Qt::ToolTipRole: - if (m_type == TEST_CLASS && m_name.isEmpty()) { + if (m_type == TestClass && m_name.isEmpty()) { return QObject::tr("

Give all test cases a name to ensure correct behavior " "when running test cases and to be able to select them.

"); } @@ -98,14 +98,14 @@ QVariant TestTreeItem::data(int /*column*/, int role) const return testTreeIcon(m_type); case Qt::CheckStateRole: switch (m_type) { - case ROOT: - case TEST_DATAFUNCTION: - case TEST_SPECIALFUNCTION: - case TEST_DATATAG: + case Root: + case TestDataFunction: + case TestSpecialFunction: + case TestDataTag: return QVariant(); - case TEST_CLASS: + case TestClass: return m_name.isEmpty() ? QVariant() : checked(); - case TEST_FUNCTION: + case TestFunction: if (parentItem() && parentItem()->name().isEmpty()) return QVariant(); return checked(); @@ -119,12 +119,12 @@ QVariant TestTreeItem::data(int /*column*/, int role) const } case ItalicRole: switch (m_type) { - case TEST_DATAFUNCTION: - case TEST_SPECIALFUNCTION: + case TestDataFunction: + case TestSpecialFunction: return true; - case TEST_CLASS: + case TestClass: return m_name.isEmpty(); - case TEST_FUNCTION: + case TestFunction: return parentItem() ? parentItem()->name().isEmpty() : false; default: return false; @@ -174,12 +174,12 @@ bool TestTreeItem::modifyContent(const TestTreeItem *modified) void TestTreeItem::setChecked(const Qt::CheckState checkState) { switch (m_type) { - case TEST_FUNCTION: { + case TestFunction: { m_checked = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked); parentItem()->revalidateCheckState(); break; } - case TEST_CLASS: { + case TestClass: { Qt::CheckState usedState = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked); for (int row = 0, count = childCount(); row < count; ++row) childItem(row)->setChecked(usedState); @@ -193,11 +193,11 @@ void TestTreeItem::setChecked(const Qt::CheckState checkState) Qt::CheckState TestTreeItem::checked() const { switch (m_type) { - case TEST_CLASS: - case TEST_FUNCTION: + case TestClass: + case TestFunction: return m_checked; - case TEST_DATAFUNCTION: - case TEST_SPECIALFUNCTION: + case TestDataFunction: + case TestSpecialFunction: return Qt::Unchecked; default: if (parent()) @@ -233,8 +233,8 @@ void TestTreeItem::revalidateCheckState() for (int row = 0, count = childCount(); row < count; ++row) { TestTreeItem *child = childItem(row); switch (child->type()) { - case TEST_DATAFUNCTION: - case TEST_SPECIALFUNCTION: + case TestDataFunction: + case TestSpecialFunction: continue; default: break; diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index 34ac137e044..19cd4adf7e5 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -42,16 +42,16 @@ class TestTreeItem : public Utils::TreeItem public: enum Type { - ROOT, - TEST_CLASS, - TEST_FUNCTION, - TEST_DATATAG, - TEST_DATAFUNCTION, - TEST_SPECIALFUNCTION + Root, + TestClass, + TestFunction, + TestDataTag, + TestDataFunction, + TestSpecialFunction }; TestTreeItem(const QString &name = QString(), const QString &filePath = QString(), - Type type = ROOT); + Type type = Root); virtual ~TestTreeItem(); TestTreeItem(const TestTreeItem& other); diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 7271ccfd17b..2d6d035885e 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -38,8 +38,8 @@ namespace Internal { TestTreeModel::TestTreeModel(QObject *parent) : TreeModel(parent), - m_autoTestRootItem(new TestTreeItem(tr("Auto Tests"), QString(), TestTreeItem::ROOT)), - m_quickTestRootItem(new TestTreeItem(tr("Qt Quick Tests"), QString(), TestTreeItem::ROOT)), + m_autoTestRootItem(new TestTreeItem(tr("Auto Tests"), QString(), TestTreeItem::Root)), + m_quickTestRootItem(new TestTreeItem(tr("Qt Quick Tests"), QString(), TestTreeItem::Root)), m_parser(new TestCodeParser(this)), m_connectionsInitialized(false) { @@ -134,11 +134,11 @@ bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int emit dataChanged(index, index); if (role == Qt::CheckStateRole) { switch (item->type()) { - case TestTreeItem::TEST_CLASS: + case TestTreeItem::TestClass: if (item->childCount() > 0) emit dataChanged(index.child(0, 0), index.child(item->childCount() - 1, 0)); break; - case TestTreeItem::TEST_FUNCTION: + case TestTreeItem::TestFunction: emit dataChanged(index.parent(), index.parent()); break; default: // avoid warning regarding unhandled enum member @@ -157,19 +157,19 @@ Qt::ItemFlags TestTreeModel::flags(const QModelIndex &index) const TestTreeItem *item = static_cast(itemForIndex(index)); switch(item->type()) { - case TestTreeItem::TEST_CLASS: + case TestTreeItem::TestClass: if (item->name().isEmpty()) return Qt::ItemIsEnabled | Qt::ItemIsSelectable; return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsTristate | Qt::ItemIsUserCheckable; - case TestTreeItem::TEST_FUNCTION: + case TestTreeItem::TestFunction: if (item->parentItem()->name().isEmpty()) return Qt::ItemIsEnabled | Qt::ItemIsSelectable; return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable; - case TestTreeItem::ROOT: + case TestTreeItem::Root: return Qt::ItemIsEnabled; - case TestTreeItem::TEST_DATAFUNCTION: - case TestTreeItem::TEST_SPECIALFUNCTION: - case TestTreeItem::TEST_DATATAG: + case TestTreeItem::TestDataFunction: + case TestTreeItem::TestSpecialFunction: + case TestTreeItem::TestDataTag: default: return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } @@ -313,7 +313,7 @@ QList TestTreeModel::getSelectedTests() const int grandChildCount = child->childCount(); for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) { const TestTreeItem *grandChild = child->childItem(grandChildRow); - if (grandChild->type() != TestTreeItem::TEST_FUNCTION) + if (grandChild->type() != TestTreeItem::TestFunction) continue; testFunctions << child->name() + QLatin1String("::") + grandChild->name(); } @@ -355,7 +355,7 @@ TestConfiguration *TestTreeModel::getTestConfiguration(const TestTreeItem *item) TestConfiguration *config = 0; switch (item->type()) { - case TestTreeItem::TEST_CLASS: { + case TestTreeItem::TestClass: { if (item->parent() == m_quickTestRootItem) { // Quick Test TestCase QStringList testFunctions; @@ -374,7 +374,7 @@ TestConfiguration *TestTreeModel::getTestConfiguration(const TestTreeItem *item) } break; } - case TestTreeItem::TEST_FUNCTION: { + case TestTreeItem::TestFunction: { const TestTreeItem *parent = item->parentItem(); if (parent->parent() == m_quickTestRootItem) { // it's a Quick Test function of a named TestCase @@ -390,7 +390,7 @@ TestConfiguration *TestTreeModel::getTestConfiguration(const TestTreeItem *item) } break; } - case TestTreeItem::TEST_DATATAG: { + case TestTreeItem::TestDataTag: { const TestTreeItem *function = item->parentItem(); const TestTreeItem *parent = function ? function->parentItem() : 0; if (!parent) @@ -489,7 +489,7 @@ void TestTreeModel::updateUnnamedQuickTest(const QString &mainFile, return; if (!hasUnnamedQuickTests()) - addTestTreeItem(new TestTreeItem(QString(), QString(), TestTreeItem::TEST_CLASS), QuickTest); + addTestTreeItem(new TestTreeItem(QString(), QString(), TestTreeItem::TestClass), QuickTest); TestTreeItem *unnamed = unnamedQuickTests(); foreach (const QString &functionName, functions.keys()) { @@ -730,7 +730,7 @@ bool TestTreeSortFilterModel::lessThan(const QModelIndex &left, const QModelInde { // root items keep the intended order: 1st Auto Tests, 2nd Quick Tests const TestTreeItem *leftItem = static_cast(left.internalPointer()); - if (leftItem->type() == TestTreeItem::ROOT) + if (leftItem->type() == TestTreeItem::Root) return left.row() > right.row(); const QString leftVal = m_sourceModel->data(left, Qt::DisplayRole).toString(); @@ -775,9 +775,9 @@ bool TestTreeSortFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex const TestTreeItem *item = static_cast(index.internalPointer()); switch (item->type()) { - case TestTreeItem::TEST_DATAFUNCTION: + case TestTreeItem::TestDataFunction: return m_filterMode & ShowTestData; - case TestTreeItem::TEST_SPECIALFUNCTION: + case TestTreeItem::TestSpecialFunction: return m_filterMode & ShowInitAndCleanup; default: return true; diff --git a/plugins/autotest/testvisitor.cpp b/plugins/autotest/testvisitor.cpp index 7102476a7d1..6074d76ac9e 100644 --- a/plugins/autotest/testvisitor.cpp +++ b/plugins/autotest/testvisitor.cpp @@ -83,11 +83,11 @@ bool TestVisitor::visit(CPlusPlus::Class *symbol) locationAndType.m_column = member->column() - 1; } if (specialFunctions.contains(name)) - locationAndType.m_type = TestTreeItem::TEST_SPECIALFUNCTION; + locationAndType.m_type = TestTreeItem::TestSpecialFunction; else if (name.endsWith(QLatin1String("_data"))) - locationAndType.m_type = TestTreeItem::TEST_DATAFUNCTION; + locationAndType.m_type = TestTreeItem::TestDataFunction; else - locationAndType.m_type = TestTreeItem::TEST_FUNCTION; + locationAndType.m_type = TestTreeItem::TestFunction; m_privSlots.insert(name, locationAndType); } } @@ -216,7 +216,7 @@ bool TestDataFunctionVisitor::visit(CPlusPlus::CallAST *ast) locationAndType.m_name = QString::fromUtf8(token.spell()); locationAndType.m_column = column - 1; locationAndType.m_line = line; - locationAndType.m_type = TestTreeItem::TEST_DATATAG; + locationAndType.m_type = TestTreeItem::TestDataTag; m_currentTags.append(locationAndType); } } @@ -293,7 +293,7 @@ bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast) m_testCaseLocation.m_name = m_currentDoc->fileName(); m_testCaseLocation.m_line = sourceLocation.startLine; m_testCaseLocation.m_column = sourceLocation.startColumn - 1; - m_testCaseLocation.m_type = TestTreeItem::TEST_CLASS; + m_testCaseLocation.m_type = TestTreeItem::TestClass; return true; } @@ -322,11 +322,11 @@ bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast) locationAndType.m_line = sourceLocation.startLine; locationAndType.m_column = sourceLocation.startColumn - 1; if (specialFunctions.contains(name.toString())) - locationAndType.m_type = TestTreeItem::TEST_SPECIALFUNCTION; + locationAndType.m_type = TestTreeItem::TestSpecialFunction; else if (name.endsWith(QLatin1String("_data"))) - locationAndType.m_type = TestTreeItem::TEST_DATAFUNCTION; + locationAndType.m_type = TestTreeItem::TestDataFunction; else - locationAndType.m_type = TestTreeItem::TEST_FUNCTION; + locationAndType.m_type = TestTreeItem::TestFunction; m_testFunctions.insert(name.toString(), locationAndType); } diff --git a/plugins/autotest/testxmloutputreader.cpp b/plugins/autotest/testxmloutputreader.cpp index 2f2c41b8d89..d65beee864e 100644 --- a/plugins/autotest/testxmloutputreader.cpp +++ b/plugins/autotest/testxmloutputreader.cpp @@ -160,7 +160,7 @@ void TestXmlOutputReader::processOutput() static QString className; static QString testCase; static QString dataTag; - static Result::Type result = Result::INVALID; + static Result::Type result = Result::Invalid; static QString description; static QString file; static int lineNumber = 0; @@ -184,14 +184,14 @@ void TestXmlOutputReader::processOutput() className = xmlReader.attributes().value(QStringLiteral("name")).toString(); QTC_ASSERT(!className.isEmpty(), continue); auto testResult = new TestResult(className); - testResult->setResult(Result::MESSAGE_TEST_CASE_START); + testResult->setResult(Result::MessageTestCaseStart); testResult->setDescription(tr("Executing test case %1").arg(className)); testResultCreated(testResult); } else if (currentTag == QStringLiteral("TestFunction")) { testCase = xmlReader.attributes().value(QStringLiteral("name")).toString(); QTC_ASSERT(!testCase.isEmpty(), continue); auto testResult = new TestResult(); - testResult->setResult(Result::MESSAGE_CURRENT_TEST); + testResult->setResult(Result::MessageCurrentTest); testResult->setDescription(tr("Entering test function %1::%2").arg(className, testCase)); testResultCreated(testResult); @@ -204,7 +204,7 @@ void TestXmlOutputReader::processOutput() description.clear(); duration.clear(); file.clear(); - result = Result::INVALID; + result = Result::Invalid; lineNumber = 0; const QXmlStreamAttributes &attributes = xmlReader.attributes(); result = TestResult::resultFromString( @@ -220,19 +220,19 @@ void TestXmlOutputReader::processOutput() const double value = attributes.value(QStringLiteral("value")).toDouble(); const int iterations = attributes.value(QStringLiteral("iterations")).toInt(); description = constructBenchmarkInformation(metric, value, iterations); - result = Result::BENCHMARK; + result = Result::Benchmark; } else if (currentTag == QStringLiteral("DataTag")) { cdataMode = DataTag; } else if (currentTag == QStringLiteral("Description")) { cdataMode = Description; } else if (currentTag == QStringLiteral("QtVersion")) { - result = Result::MESSAGE_INTERNAL; + result = Result::MessageInternal; cdataMode = QtVersion; } else if (currentTag == QStringLiteral("QtBuild")) { - result = Result::MESSAGE_INTERNAL; + result = Result::MessageInternal; cdataMode = QtBuild; } else if (currentTag == QStringLiteral("QTestVersion")) { - result = Result::MESSAGE_INTERNAL; + result = Result::MessageInternal; cdataMode = QTestVersion; } break; @@ -277,14 +277,14 @@ void TestXmlOutputReader::processOutput() if (!duration.isEmpty()) { auto testResult = new TestResult(className); testResult->setTestCase(testCase); - testResult->setResult(Result::MESSAGE_INTERNAL); + testResult->setResult(Result::MessageInternal); testResult->setDescription(tr("Execution took %1 ms.").arg(duration)); testResultCreated(testResult); } emit increaseProgress(); } else if (currentTag == QStringLiteral("TestCase") && !duration.isEmpty()) { auto testResult = new TestResult(className); - testResult->setResult(Result::MESSAGE_TEST_CASE_END); + testResult->setResult(Result::MessageTestCaseEnd); testResult->setDescription(tr("Test execution took %1 ms.").arg(duration)); testResultCreated(testResult); } else if (validEndTags.contains(currentTag.toString())) { From 42def5bb051dec49efbb62ce507db30571b16a3c Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 7 Dec 2015 10:21:50 +0100 Subject: [PATCH 163/200] Add basic support for gtest This patch provides the basics for detecting the googletest related code. Change-Id: I34da3e02596cdc0805f79633ecf2176807390fc1 Reviewed-by: Nikolai Kosjar --- plugins/autotest/autotest.pro | 1 + plugins/autotest/autotest.qbs | 1 + plugins/autotest/autotest_utils.h | 39 ++++++++++++++++++ plugins/autotest/testcodeparser.cpp | 62 +++++++++++++++++++++++++++++ plugins/autotest/testcodeparser.h | 1 + plugins/autotest/testtreeitem.h | 5 ++- plugins/autotest/testvisitor.cpp | 47 ++++++++++++++++++++++ plugins/autotest/testvisitor.h | 15 +++++++ 8 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 plugins/autotest/autotest_utils.h diff --git a/plugins/autotest/autotest.pro b/plugins/autotest/autotest.pro index 1a411d34908..f360aac5b8e 100644 --- a/plugins/autotest/autotest.pro +++ b/plugins/autotest/autotest.pro @@ -38,6 +38,7 @@ HEADERS += \ testcodeparser.h \ autotestplugin.h \ autotest_global.h \ + autotest_utils.h \ autotestconstants.h \ testrunner.h \ testconfiguration.h \ diff --git a/plugins/autotest/autotest.qbs b/plugins/autotest/autotest.qbs index 704394044c7..b5696184e7e 100644 --- a/plugins/autotest/autotest.qbs +++ b/plugins/autotest/autotest.qbs @@ -32,6 +32,7 @@ QtcCommercialPlugin { "autotest.qrc", "autotesticons.h", "autotest_global.h", + "autotest_utils.h", "autotestconstants.h", "autotestplugin.cpp", "autotestplugin.h", diff --git a/plugins/autotest/autotest_utils.h b/plugins/autotest/autotest_utils.h new file mode 100644 index 00000000000..a9f1ba45bf6 --- /dev/null +++ b/plugins/autotest/autotest_utils.h @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#ifndef AUTOTEST_UTILS_H +#define AUTOTEST_UTILS_H + +#include + +namespace AutoTest { +namespace Internal { + +static bool isGTestMacro(const QString ¯o) +{ + static QStringList valid = { + QStringLiteral("TEST"), QStringLiteral("TEST_F"), QStringLiteral("TEST_P") + }; + return valid.contains(macro); +} + +} // namespace Internal +} // namespace AutoTest + +#endif // AUTOTEST_UTILS_H diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 6f32e8dc582..bf1aab0399b 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -18,6 +18,7 @@ ****************************************************************************/ #include "autotestconstants.h" +#include "autotest_utils.h" #include "testcodeparser.h" #include "testinfo.h" #include "testvisitor.h" @@ -223,6 +224,26 @@ static bool includesQtQuickTest(const CPlusPlus::Document::Ptr &doc, return false; } +static bool includesGTest(const CPlusPlus::Document::Ptr &doc, + const CppTools::CppModelManager *cppMM) +{ + const QString gtestH = QLatin1String("gtest/gtest.h"); + foreach (const CPlusPlus::Document::Include &inc, doc->resolvedIncludes()) { + if (inc.resolvedFileName().endsWith(gtestH)) + return true; + } + + if (cppMM) { + const CPlusPlus::Snapshot snapshot = cppMM->snapshot(); + foreach (const QString &include, snapshot.allIncludesForDocument(doc->fileName())) { + if (include.endsWith(gtestH)) + return true; + } + } + + return false; +} + static bool qtTestLibDefined(const CppTools::CppModelManager *cppMM, const QString &fileName) { @@ -298,6 +319,24 @@ static QString quickTestName(const CPlusPlus::Document::Ptr &doc) return QString(); } +static QSet testNames(CPlusPlus::Document::Ptr &document) +{ + QSet result; + foreach (const CPlusPlus::Document::MacroUse ¯o, document->macroUses()) { + if (!macro.isFunctionLike()) + continue; + if (AutoTest::Internal::isGTestMacro(QLatin1String(macro.macro().name()))) { + const QVector args = macro.arguments(); + if (args.size() != 2) + continue; + const CPlusPlus::Document::Block name = args.first(); + result.insert(QLatin1String(getFileContent(document->fileName()) + .mid(name.bytesBegin(), name.bytesEnd() - name.bytesBegin()))); + } + } + return result; +} + static QList scanDirectoryForQuickTestQmlFiles(const QString &srcDir) { QStringList dirs(srcDir); @@ -494,6 +533,15 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr document) return; } } + + if (includesGTest(document, modelManager)) { + const QSet &names = testNames(document); + if (!names.isEmpty()) { + handleGTest(document->fileName(), names); + return; + } + } + // could not find the class to test, or QTest is not included and QT_TESTLIB_LIB defined // maybe file is only a referenced file if (m_cppDocMap.contains(fileName)) { @@ -547,6 +595,20 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr document) } } +void TestCodeParser::handleGTest(const QString &filePath, const QSet &names) +{ + const QByteArray &fileContent = getFileContent(filePath); + const CPlusPlus::Snapshot snapshot = CPlusPlus::CppModelManagerBase::instance()->snapshot(); + CPlusPlus::Document::Ptr document = snapshot.preprocessedDocument(fileContent, filePath); + document->check(); + CPlusPlus::AST *ast = document->translationUnit()->ast(); + GTestVisitor visitor(document); + visitor.accept(ast); + + QMap result = visitor.gtestFunctions(); + QTC_CHECK(names.contains(result.keys().toSet())); +} + void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document) { if (m_codeModelParsing) { diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 3c5529f63a6..d966b363d4b 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -82,6 +82,7 @@ public slots: void updateTestTree(); void checkDocumentForTestCode(CPlusPlus::Document::Ptr document); void handleQtQuickTest(CPlusPlus::Document::Ptr document); + void handleGTest(const QString &filePath, const QSet &names); void onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document); void onQmlDocumentUpdated(const QmlJS::Document::Ptr &document); diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index 19cd4adf7e5..c228b325a6d 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -47,7 +47,10 @@ public: TestFunction, TestDataTag, TestDataFunction, - TestSpecialFunction + TestSpecialFunction, + GTestCase, // should we distinguish between Case and Fixture? + GTestName, + GTestNameDisabled }; TestTreeItem(const QString &name = QString(), const QString &filePath = QString(), diff --git a/plugins/autotest/testvisitor.cpp b/plugins/autotest/testvisitor.cpp index 6074d76ac9e..9a0c51961d6 100644 --- a/plugins/autotest/testvisitor.cpp +++ b/plugins/autotest/testvisitor.cpp @@ -17,6 +17,7 @@ ** ****************************************************************************/ +#include "autotest_utils.h" #include "testvisitor.h" #include @@ -339,5 +340,51 @@ bool TestQmlVisitor::visit(QmlJS::AST::StringLiteral *ast) return false; } +/********************** Google Test Function AST Visitor **********************/ + +GTestVisitor::GTestVisitor(CPlusPlus::Document::Ptr doc) + : CPlusPlus::ASTVisitor(doc->translationUnit()) + , m_document(doc) +{ +} + +bool GTestVisitor::visit(CPlusPlus::FunctionDefinitionAST *ast) +{ + if (!ast || !ast->declarator || !ast->declarator->core_declarator) + return false; + + CPlusPlus::DeclaratorIdAST *id = ast->declarator->core_declarator->asDeclaratorId(); + if (!id || !ast->symbol || ast->symbol->argumentCount() != 2) + return false; + + CPlusPlus::LookupContext lc; + const QString prettyName = m_overview.prettyName(lc.fullyQualifiedName(ast->symbol)); + if (!AutoTest::Internal::isGTestMacro(prettyName)) + return false; + + CPlusPlus::Argument *testCaseNameArg = ast->symbol->argumentAt(0)->asArgument(); + CPlusPlus::Argument *testNameArg = ast->symbol->argumentAt(1)->asArgument(); + if (testCaseNameArg && testNameArg) { + const QString &testCaseName = m_overview.prettyType(testCaseNameArg->type()); + const QString &testName = m_overview.prettyType(testNameArg->type()); + + bool disabled = testName.startsWith(QLatin1String("DISABLED_")); + unsigned line = 0; + unsigned column = 0; + unsigned token = id->firstToken(); + m_document->translationUnit()->getTokenStartPosition(token, &line, &column); + + TestCodeLocationAndType locationAndType; + locationAndType.m_name = disabled ? testName.mid(9) : testName; + locationAndType.m_line = line; + locationAndType.m_column = column - 1; + locationAndType.m_type = disabled ? TestTreeItem::GTestNameDisabled + : TestTreeItem::GTestName; + m_gtestFunctions[testCaseName].append(locationAndType); + } + + return false; +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testvisitor.h b/plugins/autotest/testvisitor.h index 4441eb26f8a..bbccffd4e18 100644 --- a/plugins/autotest/testvisitor.h +++ b/plugins/autotest/testvisitor.h @@ -123,6 +123,21 @@ private: }; +class GTestVisitor : public CPlusPlus::ASTVisitor +{ +public: + GTestVisitor(CPlusPlus::Document::Ptr doc); + bool visit(CPlusPlus::FunctionDefinitionAST *ast); + + QMap gtestFunctions() const { return m_gtestFunctions; } + +private: + CPlusPlus::Document::Ptr m_document; + CPlusPlus::Overview m_overview; + QMap m_gtestFunctions; + +}; + } // namespace Internal } // namespace Autotest From 8e3d25290e9d64825c4a256e8a955589f6184f8f Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 7 Dec 2015 15:15:00 +0100 Subject: [PATCH 164/200] Enhance test tree model and item to support gtest Change-Id: I982edc1e390623fa9935d8f70fc29474f56ecac5 Reviewed-by: Nikolai Kosjar --- plugins/autotest/testtreeitem.cpp | 6 ++++++ plugins/autotest/testtreeitemdelegate.cpp | 4 ++++ plugins/autotest/testtreemodel.cpp | 13 ++++++++++++- plugins/autotest/testtreemodel.h | 4 +++- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index 6b4c5b4bc59..7b1196c6cc3 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -73,6 +73,9 @@ static QIcon testTreeIcon(TestTreeItem::Type type) QIcon(QLatin1String(":/images/func.png")), QIcon(QLatin1String(":/images/data.png")) }; + if (type == TestTreeItem::GTestCase) + return icons[1]; + if (int(type) >= int(sizeof icons / sizeof *icons)) return icons[2]; return icons[type]; @@ -102,6 +105,9 @@ QVariant TestTreeItem::data(int /*column*/, int role) const case TestDataFunction: case TestSpecialFunction: case TestDataTag: + case GTestCase: + case GTestName: + case GTestNameDisabled: return QVariant(); case TestClass: return m_name.isEmpty() ? QVariant() : checked(); diff --git a/plugins/autotest/testtreeitemdelegate.cpp b/plugins/autotest/testtreeitemdelegate.cpp index 7068c064724..17475e2326a 100644 --- a/plugins/autotest/testtreeitemdelegate.cpp +++ b/plugins/autotest/testtreeitemdelegate.cpp @@ -64,6 +64,10 @@ void TestTreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem & } } + // paint disabled googletests in gray + if (index.data(TypeRole).toInt() == TestTreeItem::GTestNameDisabled) + opt.palette.setColor(QPalette::Text, QColor(0xa0, 0xa0, 0xa0)); + QStyledItemDelegate::paint(painter, opt, index); } diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 2d6d035885e..e1334725686 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -40,11 +40,13 @@ TestTreeModel::TestTreeModel(QObject *parent) : TreeModel(parent), m_autoTestRootItem(new TestTreeItem(tr("Auto Tests"), QString(), TestTreeItem::Root)), m_quickTestRootItem(new TestTreeItem(tr("Qt Quick Tests"), QString(), TestTreeItem::Root)), + m_googleTestRootItem(new TestTreeItem(tr("Google Tests"), QString(), TestTreeItem::Root)), m_parser(new TestCodeParser(this)), m_connectionsInitialized(false) { rootItem()->appendChild(m_autoTestRootItem); rootItem()->appendChild(m_quickTestRootItem); + rootItem()->appendChild(m_googleTestRootItem); connect(m_parser, &TestCodeParser::cacheCleared, this, &TestTreeModel::removeAllTestItems, Qt::QueuedConnection); @@ -170,6 +172,9 @@ Qt::ItemFlags TestTreeModel::flags(const QModelIndex &index) const case TestTreeItem::TestDataFunction: case TestTreeItem::TestSpecialFunction: case TestTreeItem::TestDataTag: + case TestTreeItem::GTestCase: + case TestTreeItem::GTestName: + case TestTreeItem::GTestNameDisabled: default: return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } @@ -177,7 +182,8 @@ Qt::ItemFlags TestTreeModel::flags(const QModelIndex &index) const bool TestTreeModel::hasTests() const { - return m_autoTestRootItem->childCount() > 0 || m_quickTestRootItem->childCount() > 0; + return m_autoTestRootItem->childCount() > 0 || m_quickTestRootItem->childCount() > 0 + || m_googleTestRootItem->childCount() > 0; } QList TestTreeModel::getAllTestCases() const @@ -533,6 +539,7 @@ void TestTreeModel::removeAllTestItems() { m_autoTestRootItem->removeChildren(); m_quickTestRootItem->removeChildren(); + m_googleTestRootItem->removeChildren(); emit testTreeModelChanged(); } @@ -558,6 +565,8 @@ TestTreeItem *TestTreeModel::rootItemForType(TestTreeModel::Type type) return m_autoTestRootItem; case QuickTest: return m_quickTestRootItem; + case GoogleTest: + return m_googleTestRootItem; } QTC_ASSERT(false, return 0); } @@ -569,6 +578,8 @@ QModelIndex TestTreeModel::rootIndexForType(TestTreeModel::Type type) return index(0, 0); case QuickTest: return index(1, 0); + case GoogleTest: + return index(2, 0); } QTC_ASSERT(false, return QModelIndex()); } diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index fe0a8d702b7..0a2a5e0be58 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -42,7 +42,8 @@ class TestTreeModel : public Utils::TreeModel public: enum Type { AutoTest, - QuickTest + QuickTest, + GoogleTest }; static TestTreeModel* instance(); @@ -95,6 +96,7 @@ private: TestTreeItem *m_autoTestRootItem; TestTreeItem *m_quickTestRootItem; + TestTreeItem *m_googleTestRootItem; TestCodeParser *m_parser; bool m_connectionsInitialized; QAtomicInt m_refCounter; From db0ff4f940f4eb858c8fe14608fe91a84c4d8b2e Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 7 Dec 2015 15:18:25 +0100 Subject: [PATCH 165/200] Display gtest related tests inside test tree model Change-Id: I8f7a80e1b136f03a1437dd9c7ae0e6f4db0e2bcc Reviewed-by: Niels Weber --- plugins/autotest/testcodeparser.cpp | 56 +++++++++++++++++++++++++++++ plugins/autotest/testcodeparser.h | 7 ++++ plugins/autotest/testinfo.cpp | 8 +++++ plugins/autotest/testinfo.h | 20 +++++++++++ plugins/autotest/testtreemodel.cpp | 39 +++++++++++++++++++- plugins/autotest/testtreemodel.h | 1 + 6 files changed, 130 insertions(+), 1 deletion(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index bf1aab0399b..1bc78f25b3a 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -459,6 +459,20 @@ static TestTreeItem *constructTestTreeItem(const QString &fileName, return treeItem; } +static TestTreeItem *constructGTestTreeItem(const QString &filePath, const QString &caseName, + const TestCodeLocationList &testNames) +{ + TestTreeItem *item = new TestTreeItem(caseName, QString(), TestTreeItem::GTestCase); + foreach (const TestCodeLocationAndType &locationAndType, testNames) { + TestTreeItem *treeItemChild = new TestTreeItem(locationAndType.m_name, filePath, + locationAndType.m_type); + treeItemChild->setLine(locationAndType.m_line); + treeItemChild->setColumn(locationAndType.m_column); + item->appendChild(treeItemChild); + } + return item; +} + /****** end of helpers ******/ // used internally to indicate a parse that failed due to having triggered a parse for a file that @@ -607,6 +621,7 @@ void TestCodeParser::handleGTest(const QString &filePath, const QSet &n QMap result = visitor.gtestFunctions(); QTC_CHECK(names.contains(result.keys().toSet())); + updateGTests(document, result); } void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document) @@ -801,6 +816,8 @@ void TestCodeParser::clearCache() m_cppDocMap.clear(); m_quickDocMap.clear(); m_unnamedQuickDocList.clear(); + m_gtestDocMap.clear(); + m_gtestDocList.clear(); emit cacheCleared(); } @@ -810,6 +827,9 @@ void TestCodeParser::removeTestsIfNecessary(const QString &fileName) if (m_cppDocMap.contains(fileName)) { m_cppDocMap.remove(fileName); emit testItemsRemoved(fileName, TestTreeModel::AutoTest); + } else if (m_gtestDocMap.contains(fileName)) { + m_gtestDocMap.remove(fileName); + emit testItemsRemoved(fileName, TestTreeModel::GoogleTest); } else { // handle Qt Quick Tests QList toBeRemoved; foreach (const QString &file, m_quickDocMap.keys()) { @@ -997,6 +1017,33 @@ void TestCodeParser::updateModelAndQuickDocMap(QmlJS::Document::Ptr document, } } +void TestCodeParser::updateGTests(const CPlusPlus::Document::Ptr &doc, + const QMap &tests) +{ + const QString &fileName = doc->fileName(); + removeGTestsByName(fileName); + + QString proFile; + const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + QList ppList = cppMM->projectPart(fileName); + if (ppList.size()) + proFile = ppList.at(0)->projectFile; + + foreach (const QString &testName, tests.keys()) { + TestTreeItem *item = constructGTestTreeItem(fileName, testName, tests.value(testName)); + TestInfo info(item->name(), item->getChildNames(), doc->revision(), doc->editorRevision()); + info.setProfile(proFile); + foreach (const TestCodeLocationAndType &testSet, tests.value(testName)) { + GTestInfo gtestInfo(testName, testSet.m_name, fileName); + if (testSet.m_type == TestTreeItem::GTestNameDisabled) + gtestInfo.setEnabled(false); + m_gtestDocList.append(gtestInfo); + } + emit testItemCreated(item, TestTreeModel::GoogleTest); + m_gtestDocMap.insert(fileName, info); + } +} + void TestCodeParser::removeUnnamedQuickTestsByName(const QString &fileName) { for (int i = m_unnamedQuickDocList.size() - 1; i >= 0; --i) { @@ -1006,6 +1053,15 @@ void TestCodeParser::removeUnnamedQuickTestsByName(const QString &fileName) emit unnamedQuickTestsRemoved(fileName); } +void TestCodeParser::removeGTestsByName(const QString &fileName) +{ + for (int i = m_gtestDocList.size() - 1; i >= 0; --i) + if (m_gtestDocList.at(i).fileName() == fileName) + m_gtestDocList.removeAt(i); + + emit gTestsRemoved(fileName); +} + #ifdef WITH_TESTS int TestCodeParser::autoTestsCount() const { diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index d966b363d4b..2889b5a041a 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -40,6 +40,7 @@ namespace Internal { struct TestCodeLocationAndType; class TestInfo; class UnnamedQuickTestInfo; +class GTestInfo; class TestCodeParser : public QObject { @@ -72,6 +73,7 @@ signals: void unnamedQuickTestsUpdated(const QString &mainFile, const QMap &functions); void unnamedQuickTestsRemoved(const QString &filePath); + void gTestsRemoved(const QString &filePath); void parsingStarted(); void parsingFinished(); void parsingFailed(); @@ -106,12 +108,17 @@ private: const QString &declaringFile, TestTreeItem *testItem); void updateModelAndQuickDocMap(QmlJS::Document::Ptr document, const QString &referencingFile, TestTreeItem *testItem); + void updateGTests(const CPlusPlus::Document::Ptr &doc, + const QMap &tests); void removeUnnamedQuickTestsByName(const QString &fileName); + void removeGTestsByName(const QString &fileName); TestTreeModel *m_model; QMap m_cppDocMap; QMap m_quickDocMap; + QMap m_gtestDocMap; QList m_unnamedQuickDocList; + QList m_gtestDocList; bool m_codeModelParsing; bool m_fullUpdatePostponed; bool m_partialUpdatePostponed; diff --git a/plugins/autotest/testinfo.cpp b/plugins/autotest/testinfo.cpp index b83c8b61d13..7385f159884 100644 --- a/plugins/autotest/testinfo.cpp +++ b/plugins/autotest/testinfo.cpp @@ -42,5 +42,13 @@ UnnamedQuickTestInfo::UnnamedQuickTestInfo(const QString &function, const QStrin { } +GTestInfo::GTestInfo(const QString &caseName, const QString &setName, const QString &file) + : m_caseName(caseName), + m_setName(setName), + m_fileName(file), + m_enabled(true) +{ +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testinfo.h b/plugins/autotest/testinfo.h index 21fc1200838..374102ed204 100644 --- a/plugins/autotest/testinfo.h +++ b/plugins/autotest/testinfo.h @@ -71,6 +71,26 @@ private: QString m_fileName; }; +class GTestInfo { +public: + explicit GTestInfo(const QString &caseName, const QString &setName, const QString &file); + + const QString caseName() const { return m_caseName; } + void setCaseName(const QString &caseName) { m_caseName = caseName; } + const QString setName() const { return m_setName; } + void setSetName(const QString &setName) { m_setName = setName; } + const QString fileName() const { return m_fileName; } + void setFileName(const QString &fileName) { m_fileName = fileName; } + bool isEnabled() const { return m_enabled; } + void setEnabled(bool enabled) { m_enabled = enabled; } + +private: + QString m_caseName; + QString m_setName; + QString m_fileName; + bool m_enabled; +}; + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index e1334725686..342ef7a184a 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -60,6 +60,8 @@ TestTreeModel::TestTreeModel(QObject *parent) : this, &TestTreeModel::updateUnnamedQuickTest, Qt::QueuedConnection); connect(m_parser, &TestCodeParser::unnamedQuickTestsRemoved, this, &TestTreeModel::removeUnnamedQuickTests, Qt::QueuedConnection); + connect(m_parser, &TestCodeParser::gTestsRemoved, + this, &TestTreeModel::removeGTests, Qt::QueuedConnection); // CppTools::CppModelManagerInterface *cppMM = CppTools::CppModelManagerInterface::instance(); // if (cppMM) { @@ -481,10 +483,45 @@ void TestTreeModel::removeUnnamedQuickTests(const QString &filePath) emit testTreeModelChanged(); } +void TestTreeModel::removeGTests(const QString &filePath) +{ + for (int childRow = m_googleTestRootItem->childCount() - 1; childRow >= 0; --childRow) { + TestTreeItem *child = m_googleTestRootItem->childItem(childRow); + for (int grandChildRow = child->childCount() - 1; grandChildRow >= 0; --grandChildRow) { + TestTreeItem *grandChild = child->childItem(grandChildRow); + if (filePath == grandChild->filePath()) + delete takeItem(grandChild); + } + if (child->childCount() == 0) + delete takeItem(child); + } + emit testTreeModelChanged(); +} + void TestTreeModel::addTestTreeItem(TestTreeItem *item, TestTreeModel::Type type) { TestTreeItem *parent = rootItemForType(type); - parent->appendChild(item); + if (type == TestTreeModel::GoogleTest) { + // check if there's already an item with the same test name... + TestTreeItem *toBeUpdated = 0; + for (int row = 0, count = parent->childCount(); row < count; ++row) { + TestTreeItem *current = parent->childItem(row); + if (current->name() == item->name()) { + toBeUpdated = current; + break; + } + } + // ...if so we have, to update this one instead of adding a new item + if (toBeUpdated) { + for (int row = 0, count = item->childCount(); row < count; ++row) + toBeUpdated->appendChild(new TestTreeItem(*item->childItem(row))); + delete item; + } else { + parent->appendChild(item); + } + } else { + parent->appendChild(item); + } emit testTreeModelChanged(); } diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 0a2a5e0be58..bef6ec86f00 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -84,6 +84,7 @@ private: void removeAllTestItems(); void removeTestTreeItems(const QString &filePath, Type type); void removeUnnamedQuickTests(const QString &filePath); + void removeGTests(const QString &filePath); TestTreeItem *unnamedQuickTests() const; TestTreeItem *rootItemForType(Type type); From 650be0e496041a42ea78c27e6f3bd5ee01050f4c Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 9 Dec 2015 09:46:33 +0100 Subject: [PATCH 166/200] Add capability to run gtest related tests For now this only applies for 'Run All'. To be able to run only selected tests we first have to introduce the check state for gtest related items as well. Change-Id: I196b56b7fe426f846f2be0df7e21458c2733cbd1 Reviewed-by: Niels Weber --- plugins/autotest/autotest.pro | 4 +- plugins/autotest/autotest.qbs | 4 +- plugins/autotest/testcodeparser.cpp | 4 +- plugins/autotest/testconfiguration.cpp | 32 ++++- plugins/autotest/testconfiguration.h | 8 ++ ...loutputreader.cpp => testoutputreader.cpp} | 117 +++++++++++++++++- ...stxmloutputreader.h => testoutputreader.h} | 14 ++- plugins/autotest/testresultmodel.cpp | 24 ++-- plugins/autotest/testrunner.cpp | 41 ++++-- plugins/autotest/testtreeitem.h | 2 +- plugins/autotest/testtreemodel.cpp | 21 ++++ 11 files changed, 228 insertions(+), 43 deletions(-) rename plugins/autotest/{testxmloutputreader.cpp => testoutputreader.cpp} (70%) rename plugins/autotest/{testxmloutputreader.h => testoutputreader.h} (83%) diff --git a/plugins/autotest/autotest.pro b/plugins/autotest/autotest.pro index f360aac5b8e..45ab5582909 100644 --- a/plugins/autotest/autotest.pro +++ b/plugins/autotest/autotest.pro @@ -27,7 +27,7 @@ SOURCES += \ testsettings.cpp \ testsettingspage.cpp \ testnavigationwidget.cpp \ - testxmloutputreader.cpp + testoutputreader.cpp HEADERS += \ testtreeview.h \ @@ -50,7 +50,7 @@ HEADERS += \ testsettings.h \ testsettingspage.h \ testnavigationwidget.h \ - testxmloutputreader.h \ + testoutputreader.h \ autotesticons.h RESOURCES += \ diff --git a/plugins/autotest/autotest.qbs b/plugins/autotest/autotest.qbs index b5696184e7e..17b94e0c45e 100644 --- a/plugins/autotest/autotest.qbs +++ b/plugins/autotest/autotest.qbs @@ -69,8 +69,8 @@ QtcCommercialPlugin { "testtreeview.h", "testvisitor.cpp", "testvisitor.h", - "testxmloutputreader.cpp", - "testxmloutputreader.h", + "testoutputreader.cpp", + "testoutputreader.h", ] Group { diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 1bc78f25b3a..dea7d886be4 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -460,6 +460,7 @@ static TestTreeItem *constructTestTreeItem(const QString &fileName, } static TestTreeItem *constructGTestTreeItem(const QString &filePath, const QString &caseName, + const QString &proFile, const TestCodeLocationList &testNames) { TestTreeItem *item = new TestTreeItem(caseName, QString(), TestTreeItem::GTestCase); @@ -468,6 +469,7 @@ static TestTreeItem *constructGTestTreeItem(const QString &filePath, const QStri locationAndType.m_type); treeItemChild->setLine(locationAndType.m_line); treeItemChild->setColumn(locationAndType.m_column); + treeItemChild->setMainFile(proFile); item->appendChild(treeItemChild); } return item; @@ -1030,7 +1032,7 @@ void TestCodeParser::updateGTests(const CPlusPlus::Document::Ptr &doc, proFile = ppList.at(0)->projectFile; foreach (const QString &testName, tests.keys()) { - TestTreeItem *item = constructGTestTreeItem(fileName, testName, tests.value(testName)); + TestTreeItem *item = constructGTestTreeItem(fileName, testName, proFile, tests.value(testName)); TestInfo info(item->name(), item->getChildNames(), doc->revision(), doc->editorRevision()); info.setProfile(proFile); foreach (const TestCodeLocationAndType &testSet, tests.value(testName)) { diff --git a/plugins/autotest/testconfiguration.cpp b/plugins/autotest/testconfiguration.cpp index 4b294f47820..3cf60556586 100644 --- a/plugins/autotest/testconfiguration.cpp +++ b/plugins/autotest/testconfiguration.cpp @@ -42,7 +42,8 @@ TestConfiguration::TestConfiguration(const QString &testClass, const QStringList m_testCaseCount(testCaseCount), m_unnamedOnly(false), m_project(0), - m_guessedConfiguration(false) + m_guessedConfiguration(false), + m_type(Qt) { if (testCases.size() != 0) m_testCaseCount = testCases.size(); @@ -71,6 +72,21 @@ void basicProjectInformation(Project *project, const QString &mainFilePath, QStr } } +void basicProjectInformation(Project *project, const QString &proFile, QString *displayName, + Project **targetProject) +{ + CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance(); + QList projParts = cppMM->projectInfo(project).projectParts(); + + foreach (const CppTools::ProjectPart::Ptr &part, projParts) { + if (part->projectFile == proFile) { + *displayName = part->displayName; + *targetProject = part->project; + return; + } + } +} + void extractEnvironmentInformation(LocalApplicationRunConfiguration *localRunConfiguration, QString *workDir, Utils::Environment *env) { @@ -81,7 +97,7 @@ void extractEnvironmentInformation(LocalApplicationRunConfiguration *localRunCon void TestConfiguration::completeTestInformation() { - QTC_ASSERT(!m_mainFilePath.isEmpty(), return); + QTC_ASSERT(!m_mainFilePath.isEmpty() || !m_proFile.isEmpty(), return); typedef LocalApplicationRunConfiguration LocalRunConfig; @@ -92,7 +108,7 @@ void TestConfiguration::completeTestInformation() QString targetFile; QString targetName; QString workDir; - QString proFile; + QString proFile = m_proFile; QString displayName; Project *targetProject = 0; Utils::Environment env; @@ -100,7 +116,10 @@ void TestConfiguration::completeTestInformation() bool guessedRunConfiguration = false; setProject(0); - basicProjectInformation(project, m_mainFilePath, &proFile, &displayName, &targetProject); + if (m_proFile.isEmpty()) + basicProjectInformation(project, m_mainFilePath, &proFile, &displayName, &targetProject); + else + basicProjectInformation(project, proFile, &displayName, &targetProject); Target *target = project->activeTarget(); if (!target) @@ -220,5 +239,10 @@ void TestConfiguration::setGuessedConfiguration(bool guessed) m_guessedConfiguration = guessed; } +void TestConfiguration::setTestType(TestType type) +{ + m_type = type; +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testconfiguration.h b/plugins/autotest/testconfiguration.h index e1d3bc000e6..1b2d34e0873 100644 --- a/plugins/autotest/testconfiguration.h +++ b/plugins/autotest/testconfiguration.h @@ -37,6 +37,11 @@ class TestConfiguration : public QObject { Q_OBJECT public: + enum TestType { + Qt, + GTest + }; + explicit TestConfiguration(const QString &testClass, const QStringList &testCases, int testCaseCount = 0, QObject *parent = 0); ~TestConfiguration(); @@ -55,6 +60,7 @@ public: void setProject(ProjectExplorer::Project *project); void setUnnamedOnly(bool unnamedOnly); void setGuessedConfiguration(bool guessed); + void setTestType(TestType type); QString testClass() const { return m_testClass; } QStringList testCases() const { return m_testCases; } @@ -68,6 +74,7 @@ public: ProjectExplorer::Project *project() const { return m_project; } bool unnamedOnly() const { return m_unnamedOnly; } bool guessedConfiguration() const { return m_guessedConfiguration; } + TestType testType() const { return m_type; } private: QString m_testClass; @@ -83,6 +90,7 @@ private: Utils::Environment m_environment; ProjectExplorer::Project *m_project; bool m_guessedConfiguration; + TestType m_type; }; } // namespace Internal diff --git a/plugins/autotest/testxmloutputreader.cpp b/plugins/autotest/testoutputreader.cpp similarity index 70% rename from plugins/autotest/testxmloutputreader.cpp rename to plugins/autotest/testoutputreader.cpp index d65beee864e..a6aa10d3b34 100644 --- a/plugins/autotest/testxmloutputreader.cpp +++ b/plugins/autotest/testoutputreader.cpp @@ -17,7 +17,7 @@ ** ****************************************************************************/ -#include "testxmloutputreader.h" +#include "testoutputreader.h" #include "testresult.h" #include @@ -28,6 +28,7 @@ #include #include #include +#include namespace Autotest { namespace Internal { @@ -130,11 +131,10 @@ static QString constructBenchmarkInformation(const QString &metric, double value .arg(iterations); } -TestXmlOutputReader::TestXmlOutputReader(QProcess *testApplication) - :m_testApplication(testApplication) +TestOutputReader::TestOutputReader(QProcess *testApplication, OutputType type) + : m_testApplication(testApplication) + , m_type(type) { - connect(m_testApplication, &QProcess::readyReadStandardOutput, - this, &TestXmlOutputReader::processOutput); } enum CDATAMode { @@ -146,7 +146,7 @@ enum CDATAMode { QTestVersion }; -void TestXmlOutputReader::processOutput() +void TestOutputReader::processOutput() { if (!m_testApplication || m_testApplication->state() != QProcess::Running) return; @@ -306,5 +306,110 @@ void TestXmlOutputReader::processOutput() } } +void TestOutputReader::processGTestOutput() +{ + if (!m_testApplication || m_testApplication->state() != QProcess::Running) + return; + + static QRegExp newTestStarts(QStringLiteral("^\\[-{10}\\] \\d+ tests? from (.*)$")); + static QRegExp testEnds(QStringLiteral("^\\[-{10}\\] \\d+ tests? from (.*) \\((.*)\\)$")); + static QRegExp newTestSetStarts(QStringLiteral("^\\[ RUN \\] (.*)$")); + static QRegExp testSetSuccess(QStringLiteral("^\\[ OK \\] (.*) \\((.*)\\)$")); + static QRegExp testSetFail(QStringLiteral("^\\\[ FAILED \\] (.*) \\((.*)\\)$")); + static QRegExp disabledTests(QStringLiteral("^ YOU HAVE (\\d+) DISABLED TESTS?$")); + + static QString currentTestName; + static QString currentTestSet; + static QString description; + static QByteArray unprocessed; + + while (m_testApplication->canReadLine()) + unprocessed.append(m_testApplication->readLine()); + + int lineBreak; + while ((lineBreak = unprocessed.indexOf('\n')) != -1) { + const QString line = QLatin1String(unprocessed.left(lineBreak)); + unprocessed.remove(0, lineBreak + 1); + if (line.isEmpty()) { + continue; + } + if (!line.startsWith(QLatin1Char('['))) { + description.append(line).append(QLatin1Char('\n')); + if (line.startsWith(QStringLiteral("Note:"))) { + auto testResult = new TestResult(); + testResult->setResult(Result::MessageInternal); + testResult->setDescription(line); + testResultCreated(testResult); + description.clear(); + } else if (disabledTests.exactMatch(line)) { + auto testResult = new TestResult(); + testResult->setResult(Result::MessageInternal); + int disabled = disabledTests.cap(1).toInt(); + testResult->setDescription(tr("You have %n disabled test(s).", 0, disabled)); + testResultCreated(testResult); + description.clear(); + } + continue; + } + + if (testEnds.exactMatch(line)) { + auto testResult = new TestResult(currentTestName); + testResult->setTestCase(currentTestSet); + testResult->setResult(Result::MessageTestCaseEnd); + testResult->setDescription(tr("Test execution took %1").arg(testEnds.cap(2))); + testResultCreated(testResult); + currentTestName.clear(); + currentTestSet.clear(); + } else if (newTestStarts.exactMatch(line)) { + currentTestName = newTestStarts.cap(1); + auto testResult = new TestResult(currentTestName); + testResult->setResult(Result::MessageTestCaseStart); + testResult->setDescription(tr("Executing test case %1").arg(currentTestName)); + testResultCreated(testResult); + } else if (newTestSetStarts.exactMatch(line)) { + currentTestSet = newTestSetStarts.cap(1); + auto testResult = new TestResult(); + testResult->setResult(Result::MessageCurrentTest); + testResult->setDescription(tr("Entering test set %1").arg(currentTestSet)); + testResultCreated(testResult); + } else if (testSetSuccess.exactMatch(line)) { + auto testResult = new TestResult(currentTestName); + testResult->setTestCase(currentTestSet); + testResult->setResult(Result::Pass); + testResultCreated(testResult); + testResult = new TestResult(currentTestName); + testResult->setTestCase(currentTestSet); + testResult->setResult(Result::MessageInternal); + testResult->setDescription(tr("Execution took %1.").arg(testSetSuccess.cap(2))); + testResultCreated(testResult); + emit increaseProgress(); + } else if (testSetFail.exactMatch(line)) { + auto testResult = new TestResult(currentTestName); + testResult->setTestCase(currentTestSet); + testResult->setResult(Result::Fail); + description.chop(1); + testResult->setDescription(description); + int firstColon = description.indexOf(QLatin1Char(':')); + if (firstColon != -1) { + int secondColon = description.indexOf(QLatin1Char(':'), firstColon + 1); + QString file = constructSourceFilePath(m_testApplication->workingDirectory(), + description.left(firstColon), + m_testApplication->program()); + QString line = description.mid(firstColon + 1, secondColon - firstColon - 1); + testResult->setFileName(file); + testResult->setLine(line.toInt()); + } + testResultCreated(testResult); + description.clear(); + testResult = new TestResult(currentTestName); + testResult->setTestCase(currentTestSet); + testResult->setResult(Result::MessageInternal); + testResult->setDescription(tr("Execution took %1.").arg(testSetFail.cap(2))); + testResultCreated(testResult); + emit increaseProgress(); + } + } +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testxmloutputreader.h b/plugins/autotest/testoutputreader.h similarity index 83% rename from plugins/autotest/testxmloutputreader.h rename to plugins/autotest/testoutputreader.h index feb99c46b21..532e081a03f 100644 --- a/plugins/autotest/testxmloutputreader.h +++ b/plugins/autotest/testoutputreader.h @@ -24,7 +24,6 @@ #include #include -#include QT_BEGIN_NAMESPACE class QProcess; @@ -33,14 +32,20 @@ QT_END_NAMESPACE namespace Autotest { namespace Internal { -class TestXmlOutputReader : public QObject +class TestOutputReader : public QObject { Q_OBJECT public: - TestXmlOutputReader(QProcess *testApplication); + enum OutputType { + Qt, + GTest + }; + + TestOutputReader(QProcess *testApplication, OutputType type = Qt); public slots: void processOutput(); + void processGTestOutput(); signals: void testResultCreated(TestResult *testResult); @@ -48,9 +53,10 @@ signals: private: QProcess *m_testApplication; // not owned + OutputType m_type; }; } // namespace Internal } // namespace Autotest -#endif // TESTXMLOUTPUTREADER_H +#endif // TESTOUTPUTREADER_H diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index 65afcdd5e8e..8ab0aa8a14c 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -160,18 +160,20 @@ void TestResultModel::addTestResult(TestResult *testResult, bool autoExpand) TestResultItem *newItem = new TestResultItem(testResult); // FIXME this might be totally wrong... we need some more unique information! - for (int row = lastRow; row >= 0; --row) { - TestResultItem *current = static_cast(topLevelItems.at(row)); - const TestResult *result = current->testResult(); - if (result && result->className() == testResult->className()) { - current->appendChild(newItem); - if (autoExpand) - current->expand(); - if (testResult->result() == Result::MessageTestCaseEnd) { - current->updateResult(); - emit dataChanged(current->index(), current->index()); + if (!testResult->className().isEmpty()) { + for (int row = lastRow; row >= 0; --row) { + TestResultItem *current = static_cast(topLevelItems.at(row)); + const TestResult *result = current->testResult(); + if (result && result->className() == testResult->className()) { + current->appendChild(newItem); + if (autoExpand) + current->expand(); + if (testResult->result() == Result::MessageTestCaseEnd) { + current->updateResult(); + emit dataChanged(current->index(), current->index()); + } + return; } - return; } } // if we have a MessageCurrentTest present, add the new top level item before it diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index aef4b53a9f2..a8ceaa34612 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -22,7 +22,7 @@ #include "autotestplugin.h" #include "testresultspane.h" #include "testsettings.h" -#include "testxmloutputreader.h" +#include "testoutputreader.h" #include #include @@ -36,6 +36,7 @@ #include #include +#include #include namespace Autotest { @@ -109,10 +110,14 @@ void performTestRun(QFutureInterface &futureInterface, const QString metricsOption, TestRunner* testRunner) { int testCaseCount = 0; + bool hasQtTests = false; + bool hasGTests = false; foreach (TestConfiguration *config, selectedTests) { config->completeTestInformation(); if (config->project()) { testCaseCount += config->testCaseCount(); + hasQtTests |= config->testType() == TestConfiguration::Qt; + hasGTests |= config->testType() == TestConfiguration::GTest; } else { emitTestResultCreated(new FaultyTestResult(Result::MessageWarn, QObject::tr("Project is null for \"%1\". Removing from test run.\n" @@ -127,18 +132,28 @@ void performTestRun(QFutureInterface &futureInterface, futureInterface.cancel(); // this kills the process if that is still in the running loop }); - TestXmlOutputReader xmlReader(&testProcess); - QObject::connect(&xmlReader, &TestXmlOutputReader::increaseProgress, [&] () { + TestOutputReader outputReader(&testProcess); + QObject::connect(&outputReader, &TestOutputReader::increaseProgress, [&] () { futureInterface.setProgressValue(futureInterface.progressValue() + 1); }); - QObject::connect(&xmlReader, &TestXmlOutputReader::testResultCreated, &emitTestResultCreated); - - QObject::connect(&testProcess, &QProcess::readyRead, &xmlReader, &TestXmlOutputReader::processOutput); + QObject::connect(&outputReader, &TestOutputReader::testResultCreated, &emitTestResultCreated); futureInterface.setProgressRange(0, testCaseCount); futureInterface.setProgressValue(0); + QMetaObject::Connection connection; foreach (const TestConfiguration *testConfiguration, selectedTests) { + if (connection) + QObject::disconnect(connection); + + TestConfiguration::TestType testType = testConfiguration->testType(); + if (testType == TestConfiguration::Qt) { + connection = QObject::connect(&testProcess, &QProcess::readyRead, &outputReader, + &TestOutputReader::processOutput); + } else { + connection = QObject::connect(&testProcess, &QProcess::readyRead, &outputReader, + &TestOutputReader::processGTestOutput); + } if (futureInterface.isCanceled()) break; @@ -155,12 +170,14 @@ void performTestRun(QFutureInterface &futureInterface, continue; } - QStringList argumentList(QLatin1String("-xml")); - if (!metricsOption.isEmpty()) - argumentList << metricsOption; - if (testConfiguration->testCases().count()) - argumentList << testConfiguration->testCases(); - testProcess.setArguments(argumentList); + if (testType == TestConfiguration::Qt) { + QStringList argumentList(QLatin1String("-xml")); + if (!metricsOption.isEmpty()) + argumentList << metricsOption; + if (testConfiguration->testCases().count()) + argumentList << testConfiguration->testCases(); + testProcess.setArguments(argumentList); + } testProcess.setWorkingDirectory(testConfiguration->workingDirectory()); if (Utils::HostOsInfo::isWindowsHost()) diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index c228b325a6d..dbd9b4a8ab4 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -86,7 +86,7 @@ private: Type m_type; unsigned m_line; unsigned m_column; - QString m_mainFile; + QString m_mainFile; // main for Quick tests, project file for gtest }; struct TestCodeLocationAndType { diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 342ef7a184a..6addc97ca19 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -236,6 +236,27 @@ QList TestTreeModel::getAllTestCases() const result << tc; } + foundMains.clear(); + + // get all Google Tests + for (int row = 0, count = m_googleTestRootItem->childCount(); row < count; ++row) { + const TestTreeItem *child = m_googleTestRootItem->childItem(row); + for (int childRow = 0, childCount = child->childCount(); childRow < childCount; ++childRow) { + const QString &proFilePath = child->childItem(childRow)->mainFile(); + foundMains.insert(proFilePath, foundMains.contains(proFilePath) + ? foundMains.value(proFilePath) + 1 : 1); + } + } + + foreach (const QString &proFile, foundMains.keys()) { + TestConfiguration *tc = new TestConfiguration(QString(), QStringList(), + foundMains.value(proFile)); + tc->setProFile(proFile); + tc->setProject(project); + tc->setTestType(TestConfiguration::GTest); + result << tc; + } + return result; } From 1cfe46df016b669f8423654e7e06fb3bd9dcef64 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 9 Dec 2015 10:48:27 +0100 Subject: [PATCH 167/200] Make gtest related items checkable This is a preparation for supporting 'Run Selected Tests' for gtest related tests. Change-Id: I4fc46b9c394d8c748b42b2cda2d27d3597a1c273 Reviewed-by: Niels Weber --- plugins/autotest/testtreeitem.cpp | 19 ++++++++++++++----- plugins/autotest/testtreemodel.cpp | 9 ++++++--- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index 7b1196c6cc3..afba068ac47 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -39,6 +39,9 @@ TestTreeItem::TestTreeItem(const QString &name, const QString &filePath, Type ty switch (m_type) { case TestClass: case TestFunction: + case GTestCase: + case GTestName: + case GTestNameDisabled: m_checked = Qt::Checked; break; default: @@ -105,13 +108,13 @@ QVariant TestTreeItem::data(int /*column*/, int role) const case TestDataFunction: case TestSpecialFunction: case TestDataTag: - case GTestCase: - case GTestName: - case GTestNameDisabled: return QVariant(); case TestClass: + case GTestCase: return m_name.isEmpty() ? QVariant() : checked(); case TestFunction: + case GTestName: + case GTestNameDisabled: if (parentItem() && parentItem()->name().isEmpty()) return QVariant(); return checked(); @@ -180,12 +183,15 @@ bool TestTreeItem::modifyContent(const TestTreeItem *modified) void TestTreeItem::setChecked(const Qt::CheckState checkState) { switch (m_type) { - case TestFunction: { + case TestFunction: + case GTestName: + case GTestNameDisabled: { m_checked = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked); parentItem()->revalidateCheckState(); break; } - case TestClass: { + case TestClass: + case GTestCase: { Qt::CheckState usedState = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked); for (int row = 0, count = childCount(); row < count; ++row) childItem(row)->setChecked(usedState); @@ -201,6 +207,9 @@ Qt::CheckState TestTreeItem::checked() const switch (m_type) { case TestClass: case TestFunction: + case GTestCase: + case GTestName: + case GTestNameDisabled: return m_checked; case TestDataFunction: case TestSpecialFunction: diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 6addc97ca19..770b92a4237 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -139,10 +139,13 @@ bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int if (role == Qt::CheckStateRole) { switch (item->type()) { case TestTreeItem::TestClass: + case TestTreeItem::GTestCase: if (item->childCount() > 0) emit dataChanged(index.child(0, 0), index.child(item->childCount() - 1, 0)); break; case TestTreeItem::TestFunction: + case TestTreeItem::GTestName: + case TestTreeItem::GTestNameDisabled: emit dataChanged(index.parent(), index.parent()); break; default: // avoid warning regarding unhandled enum member @@ -162,10 +165,13 @@ Qt::ItemFlags TestTreeModel::flags(const QModelIndex &index) const TestTreeItem *item = static_cast(itemForIndex(index)); switch(item->type()) { case TestTreeItem::TestClass: + case TestTreeItem::GTestCase: if (item->name().isEmpty()) return Qt::ItemIsEnabled | Qt::ItemIsSelectable; return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsTristate | Qt::ItemIsUserCheckable; case TestTreeItem::TestFunction: + case TestTreeItem::GTestName: + case TestTreeItem::GTestNameDisabled: if (item->parentItem()->name().isEmpty()) return Qt::ItemIsEnabled | Qt::ItemIsSelectable; return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable; @@ -174,9 +180,6 @@ Qt::ItemFlags TestTreeModel::flags(const QModelIndex &index) const case TestTreeItem::TestDataFunction: case TestTreeItem::TestSpecialFunction: case TestTreeItem::TestDataTag: - case TestTreeItem::GTestCase: - case TestTreeItem::GTestName: - case TestTreeItem::GTestNameDisabled: default: return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } From ebfc118c35a97d4e83aff760fae85279ac80e080 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 9 Dec 2015 13:21:23 +0100 Subject: [PATCH 168/200] Add capability to execute selected gtests Change-Id: Ib7354d6e86176852b2e3bb01aed091db8036bfdf Reviewed-by: Niels Weber --- plugins/autotest/testrunner.cpp | 8 ++++++++ plugins/autotest/testtreemodel.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index a8ceaa34612..7c613984bd6 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -177,6 +177,14 @@ void performTestRun(QFutureInterface &futureInterface, if (testConfiguration->testCases().count()) argumentList << testConfiguration->testCases(); testProcess.setArguments(argumentList); + } else { // TestConfiguration::GTest + const QStringList &testSets = testConfiguration->testCases(); + if (testSets.size()) { + QStringList argumentList; + argumentList << QLatin1String("--gtest_filter=") + + testSets.join(QLatin1Char(':')); + testProcess.setArguments(argumentList); + } } testProcess.setWorkingDirectory(testConfiguration->workingDirectory()); diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 770b92a4237..91811f621f1 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -376,6 +376,34 @@ QList TestTreeModel::getSelectedTests() const if (!config->unnamedOnly()) result << config; + // get selected Google Tests + QMap proFilesWithEnabledTestSets; + + for (int row = 0, count = m_googleTestRootItem->childCount(); row < count; ++row) { + const TestTreeItem *child = m_googleTestRootItem->childItem(row); + if (child->checked() == Qt::Unchecked) // add this test name to disabled list ? + continue; + + int grandChildCount = child->childCount(); + for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) { + const TestTreeItem *grandChild = child->childItem(grandChildRow); + const QString &proFile = grandChild->mainFile(); + QStringList enabled = proFilesWithEnabledTestSets.value(proFile); + if (grandChild->checked() == Qt::Checked) + enabled << child->name() + QLatin1Char('.') + grandChild->name(); + proFilesWithEnabledTestSets.insert(proFile, enabled); + } + } + + foreach (const QString &proFile, proFilesWithEnabledTestSets.keys()) { + TestConfiguration *tc = new TestConfiguration(QString(), + proFilesWithEnabledTestSets.value(proFile)); + tc->setTestType(TestConfiguration::GTest); + tc->setProFile(proFile); + tc->setProject(project); + result << tc; + } + return result; } From a88d3df334f5711c75da89b7ca2baaf7e4f3775f Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 9 Dec 2015 13:32:26 +0100 Subject: [PATCH 169/200] Enable (De)Select All for gtests as well Change-Id: Ie9c4c12b57f37ff31aaccf344bd12ea737a14386 Reviewed-by: Niels Weber --- plugins/autotest/testtreeview.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/autotest/testtreeview.cpp b/plugins/autotest/testtreeview.cpp index 5675e9266f8..39105b6bdcb 100644 --- a/plugins/autotest/testtreeview.cpp +++ b/plugins/autotest/testtreeview.cpp @@ -70,8 +70,8 @@ void TestTreeView::changeCheckStateAll(const Qt::CheckState checkState) { const TestTreeModel *model = TestTreeModel::instance(); - // 2 == Auto Tests and Quick Tests - must be raised if there will be others - for (int rootRow = 0; rootRow < 2; ++rootRow) { + // 3 == Auto Tests, Quick Tests and Google Tests - must be raised if there will be others + for (int rootRow = 0; rootRow < 3; ++rootRow) { QModelIndex currentRootIndex = model->index(rootRow, 0, rootIndex()); if (!currentRootIndex.isValid()) return; From b13373e45e4c6105d665a1c70029d446c4f968cc Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 9 Dec 2015 14:09:49 +0100 Subject: [PATCH 170/200] Enable 'Run This Test' for gtest items Change-Id: Ia0fb93a4bbc225c45352f0f818262f5b6ff9d6d6 Reviewed-by: Niels Weber --- plugins/autotest/testnavigationwidget.cpp | 8 ++++++-- plugins/autotest/testtreemodel.cpp | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index e396c807ebc..bff1b4de8d6 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -106,7 +106,9 @@ void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event) const QString &unnamed = tr(Constants::UNNAMED_QUICKTESTS); if ((type == TestTreeItem::TestFunction && index.parent().data().toString() != unnamed) || (type == TestTreeItem::TestClass && index.data().toString() != unnamed) - || (type == TestTreeItem::TestDataTag)) { + || (type == TestTreeItem::TestDataTag) + || (type == TestTreeItem::GTestCase) + || (type == TestTreeItem::GTestName)) { runThisTest = new QAction(tr("Run This Test"), &menu); runThisTest->setEnabled(enabled); connect(runThisTest, &QAction::triggered, @@ -251,7 +253,9 @@ void TestNavigationWidget::onRunThisTestTriggered() TestTreeItem *item = static_cast(sourceIndex.internalPointer()); if (item->type() == TestTreeItem::TestClass || item->type() == TestTreeItem::TestFunction - || item->type() == TestTreeItem::TestDataTag) { + || item->type() == TestTreeItem::TestDataTag + || item->type() == TestTreeItem::GTestCase + || item->type() == TestTreeItem::GTestName) { if (TestConfiguration *configuration = m_model->getTestConfiguration(item)) { TestRunner *runner = TestRunner::instance(); runner->setSelectedTests( {configuration} ); diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 91811f621f1..507e18da20c 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -461,6 +461,26 @@ TestConfiguration *TestTreeModel::getTestConfiguration(const TestTreeItem *item) config->setProject(project); break; } + case TestTreeItem::GTestCase: { + if (int childCount = item->childCount()) { + config = new TestConfiguration(QString(), + QStringList(item->name() + QLatin1String(".*"))); + config->setTestCaseCount(childCount); + config->setProFile(item->childItem(0)->mainFile()); + config->setProject(project); + config->setTestType(TestConfiguration::GTest); + } + break; + } + case TestTreeItem::GTestName: { + const TestTreeItem *parent = item->parentItem(); + config = new TestConfiguration(QString(), + QStringList(parent->name() + QLatin1Char('.') + item->name())); + config->setProFile(item->mainFile()); + config->setProject(project); + config->setTestType(TestConfiguration::GTest); + break; + } // not supported items default: return 0; From 2f1018ab24213f6aac7a15eb474082df298a0f80 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 14 Dec 2015 07:23:18 +0100 Subject: [PATCH 171/200] Fix missing MessageTestCaseEnd for Qt4 based tests Qt4 based tests have no duration, so this message had been omitted accidently. Change-Id: I11b03234c8f7fd022e951728b70ae186091c15d9 Reviewed-by: Niels Weber --- plugins/autotest/testoutputreader.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/autotest/testoutputreader.cpp b/plugins/autotest/testoutputreader.cpp index a6aa10d3b34..facf7353b62 100644 --- a/plugins/autotest/testoutputreader.cpp +++ b/plugins/autotest/testoutputreader.cpp @@ -282,10 +282,12 @@ void TestOutputReader::processOutput() testResultCreated(testResult); } emit increaseProgress(); - } else if (currentTag == QStringLiteral("TestCase") && !duration.isEmpty()) { + } else if (currentTag == QStringLiteral("TestCase")) { auto testResult = new TestResult(className); testResult->setResult(Result::MessageTestCaseEnd); - testResult->setDescription(tr("Test execution took %1 ms.").arg(duration)); + testResult->setDescription( + duration.isEmpty() ? tr("Test finished.") + : tr("Test execution took %1 ms.").arg(duration)); testResultCreated(testResult); } else if (validEndTags.contains(currentTag.toString())) { auto testResult = new TestResult(className); From e0a05d476b73d2baa31c8fde36f332a05941edf7 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 14 Dec 2015 09:44:03 +0100 Subject: [PATCH 172/200] Make string translatable Change-Id: I5a0d48e0c01fea0e3da4174083e03920a8f39479 Reviewed-by: Niels Weber --- plugins/autotest/testoutputreader.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/autotest/testoutputreader.cpp b/plugins/autotest/testoutputreader.cpp index facf7353b62..5dacfeee618 100644 --- a/plugins/autotest/testoutputreader.cpp +++ b/plugins/autotest/testoutputreader.cpp @@ -255,8 +255,7 @@ void TestOutputReader::processOutput() description = tr("Qt version: %1").arg(text.toString()); break; case QtBuild: - // FIXME due to string freeze this is not a tr() - description = QString::fromLatin1("Qt build: %1").arg(text.toString()); + description = tr("Qt build: %1").arg(text.toString()); break; case QTestVersion: description = tr("QTest version: %1").arg(text.toString()); From c8c79c409f3398a5e8b145d711f62b3c35ab11e0 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 14 Dec 2015 10:19:37 +0100 Subject: [PATCH 173/200] Make test result distinguishable more easily This additionally fixes the output of the gtest related test cases. Change-Id: Ia9e19604ffe387752b08db4a4ad9a9e255d210a3 Reviewed-by: Niels Weber --- plugins/autotest/testoutputreader.cpp | 28 ++++++++++++------------- plugins/autotest/testresult.cpp | 12 +++++++++++ plugins/autotest/testresult.h | 21 +++++++++++++++++++ plugins/autotest/testresultdelegate.cpp | 5 ++++- 4 files changed, 51 insertions(+), 15 deletions(-) diff --git a/plugins/autotest/testoutputreader.cpp b/plugins/autotest/testoutputreader.cpp index 5dacfeee618..0b77f71c63b 100644 --- a/plugins/autotest/testoutputreader.cpp +++ b/plugins/autotest/testoutputreader.cpp @@ -183,14 +183,14 @@ void TestOutputReader::processOutput() if (currentTag == QStringLiteral("TestCase")) { className = xmlReader.attributes().value(QStringLiteral("name")).toString(); QTC_ASSERT(!className.isEmpty(), continue); - auto testResult = new TestResult(className); + auto testResult = new QTestResult(className); testResult->setResult(Result::MessageTestCaseStart); testResult->setDescription(tr("Executing test case %1").arg(className)); testResultCreated(testResult); } else if (currentTag == QStringLiteral("TestFunction")) { testCase = xmlReader.attributes().value(QStringLiteral("name")).toString(); QTC_ASSERT(!testCase.isEmpty(), continue); - auto testResult = new TestResult(); + auto testResult = new QTestResult(); testResult->setResult(Result::MessageCurrentTest); testResult->setDescription(tr("Entering test function %1::%2").arg(className, testCase)); @@ -274,7 +274,7 @@ void TestOutputReader::processOutput() const QStringRef currentTag = xmlReader.name(); if (currentTag == QStringLiteral("TestFunction")) { if (!duration.isEmpty()) { - auto testResult = new TestResult(className); + auto testResult = new QTestResult(className); testResult->setTestCase(testCase); testResult->setResult(Result::MessageInternal); testResult->setDescription(tr("Execution took %1 ms.").arg(duration)); @@ -282,14 +282,14 @@ void TestOutputReader::processOutput() } emit increaseProgress(); } else if (currentTag == QStringLiteral("TestCase")) { - auto testResult = new TestResult(className); + auto testResult = new QTestResult(className); testResult->setResult(Result::MessageTestCaseEnd); testResult->setDescription( duration.isEmpty() ? tr("Test finished.") : tr("Test execution took %1 ms.").arg(duration)); testResultCreated(testResult); } else if (validEndTags.contains(currentTag.toString())) { - auto testResult = new TestResult(className); + auto testResult = new QTestResult(className); testResult->setTestCase(testCase); testResult->setDataTag(dataTag); testResult->setResult(result); @@ -337,13 +337,13 @@ void TestOutputReader::processGTestOutput() if (!line.startsWith(QLatin1Char('['))) { description.append(line).append(QLatin1Char('\n')); if (line.startsWith(QStringLiteral("Note:"))) { - auto testResult = new TestResult(); + auto testResult = new GTestResult(); testResult->setResult(Result::MessageInternal); testResult->setDescription(line); testResultCreated(testResult); description.clear(); } else if (disabledTests.exactMatch(line)) { - auto testResult = new TestResult(); + auto testResult = new GTestResult(); testResult->setResult(Result::MessageInternal); int disabled = disabledTests.cap(1).toInt(); testResult->setDescription(tr("You have %n disabled test(s).", 0, disabled)); @@ -354,7 +354,7 @@ void TestOutputReader::processGTestOutput() } if (testEnds.exactMatch(line)) { - auto testResult = new TestResult(currentTestName); + auto testResult = new GTestResult(currentTestName); testResult->setTestCase(currentTestSet); testResult->setResult(Result::MessageTestCaseEnd); testResult->setDescription(tr("Test execution took %1").arg(testEnds.cap(2))); @@ -363,29 +363,29 @@ void TestOutputReader::processGTestOutput() currentTestSet.clear(); } else if (newTestStarts.exactMatch(line)) { currentTestName = newTestStarts.cap(1); - auto testResult = new TestResult(currentTestName); + auto testResult = new GTestResult(currentTestName); testResult->setResult(Result::MessageTestCaseStart); testResult->setDescription(tr("Executing test case %1").arg(currentTestName)); testResultCreated(testResult); } else if (newTestSetStarts.exactMatch(line)) { currentTestSet = newTestSetStarts.cap(1); - auto testResult = new TestResult(); + auto testResult = new GTestResult(); testResult->setResult(Result::MessageCurrentTest); testResult->setDescription(tr("Entering test set %1").arg(currentTestSet)); testResultCreated(testResult); } else if (testSetSuccess.exactMatch(line)) { - auto testResult = new TestResult(currentTestName); + auto testResult = new GTestResult(currentTestName); testResult->setTestCase(currentTestSet); testResult->setResult(Result::Pass); testResultCreated(testResult); - testResult = new TestResult(currentTestName); + testResult = new GTestResult(currentTestName); testResult->setTestCase(currentTestSet); testResult->setResult(Result::MessageInternal); testResult->setDescription(tr("Execution took %1.").arg(testSetSuccess.cap(2))); testResultCreated(testResult); emit increaseProgress(); } else if (testSetFail.exactMatch(line)) { - auto testResult = new TestResult(currentTestName); + auto testResult = new GTestResult(currentTestName); testResult->setTestCase(currentTestSet); testResult->setResult(Result::Fail); description.chop(1); @@ -402,7 +402,7 @@ void TestOutputReader::processGTestOutput() } testResultCreated(testResult); description.clear(); - testResult = new TestResult(currentTestName); + testResult = new GTestResult(currentTestName); testResult->setTestCase(currentTestSet); testResult->setResult(Result::MessageInternal); testResult->setDescription(tr("Execution took %1.").arg(testSetFail.cap(2))); diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp index 37929f00f4f..5885c1c400a 100644 --- a/plugins/autotest/testresult.cpp +++ b/plugins/autotest/testresult.cpp @@ -37,6 +37,7 @@ TestResult::TestResult(const QString &className) : m_class(className) , m_result(Result::Invalid) , m_line(0) + , m_type(Qt) { } @@ -146,5 +147,16 @@ bool operator==(const TestResult &t1, const TestResult &t2) && t1.result() == t2.result(); } +QTestResult::QTestResult(const QString &className) + : TestResult(className) +{ +} + +GTestResult::GTestResult(const QString &className) + : TestResult(className) +{ + setTestType(GTest); +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index d28255aad0d..35158050303 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -57,6 +57,12 @@ enum Type { class TestResult { public: + enum TestType + { + Qt, + GTest + }; + TestResult(); TestResult(const QString &className); @@ -67,6 +73,7 @@ public: QString description() const { return m_description; } QString fileName() const { return m_file; } int line() const { return m_line; } + TestType type() const { return m_type; } void setDescription(const QString &description) { m_description = description; } void setFileName(const QString &fileName) { m_file = fileName; } @@ -74,6 +81,7 @@ public: void setResult(Result::Type type) { m_result = type; } void setTestCase(const QString &testCase) { m_case = testCase; } void setDataTag(const QString &dataTag) { m_dataTag = dataTag; } + void setTestType(TestType type) { m_type = type; } static Result::Type resultFromString(const QString &resultString); static Result::Type toResultType(int rt); @@ -88,6 +96,7 @@ private: QString m_description; QString m_file; int m_line; + TestType m_type; // environment? }; @@ -97,6 +106,18 @@ public: FaultyTestResult(Result::Type result, const QString &description); }; +class QTestResult : public TestResult +{ +public: + QTestResult(const QString &className = QString()); +}; + +class GTestResult : public TestResult +{ +public: + GTestResult(const QString &className = QString()); +}; + bool operator==(const TestResult &t1, const TestResult &t2); } // namespace Internal diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp index 87559465a22..a1ca6f9fe43 100644 --- a/plugins/autotest/testresultdelegate.cpp +++ b/plugins/autotest/testresultdelegate.cpp @@ -48,7 +48,10 @@ QString TestResultDelegate::outputString(const TestResult &testResult, bool sele case Result::UnexpectedPass: case Result::BlacklistedFail: case Result::BlacklistedPass: - output = testResult.className() + QLatin1String("::") + testResult.testCase(); + if (testResult.type() == TestResult::Qt) + output = testResult.className() + QLatin1String("::") + testResult.testCase(); + else // TestResult::GTest + output = testResult.testCase(); if (!testResult.dataTag().isEmpty()) output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); if (selected && !desc.isEmpty()) { From ce926564b027e7c8c18dc934f9221f7382ffa53d Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 14 Dec 2015 12:48:58 +0100 Subject: [PATCH 174/200] Handle disabled gtests more correctly Test summary now displays the number of disabled tests instead of having them printed as loose messages. Change-Id: I8ea736f789afc7c8ad6101a03fa5ca6428d92744 Reviewed-by: Niels Weber --- plugins/autotest/testoutputreader.cpp | 3 ++- plugins/autotest/testresult.h | 1 + plugins/autotest/testresultmodel.cpp | 6 +++++- plugins/autotest/testresultmodel.h | 2 ++ plugins/autotest/testresultspane.cpp | 4 ++++ 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/plugins/autotest/testoutputreader.cpp b/plugins/autotest/testoutputreader.cpp index 0b77f71c63b..c75260ef015 100644 --- a/plugins/autotest/testoutputreader.cpp +++ b/plugins/autotest/testoutputreader.cpp @@ -344,9 +344,10 @@ void TestOutputReader::processGTestOutput() description.clear(); } else if (disabledTests.exactMatch(line)) { auto testResult = new GTestResult(); - testResult->setResult(Result::MessageInternal); + testResult->setResult(Result::MessageDisabledTests); int disabled = disabledTests.cap(1).toInt(); testResult->setDescription(tr("You have %n disabled test(s).", 0, disabled)); + testResult->setLine(disabled); // misuse line property to hold number of disabled testResultCreated(testResult); description.clear(); } diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index 35158050303..a6c4f3e32a1 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -42,6 +42,7 @@ enum Type { MessageFatal, MessageInternal, INTERNAL_MESSAGES_BEGIN = MessageInternal, + MessageDisabledTests, MessageTestCaseStart, MessageTestCaseSuccess, MessageTestCaseWarn, diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index 8ab0aa8a14c..a3dac8e3192 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -116,7 +116,8 @@ void TestResultItem::updateResult() TestResultModel::TestResultModel(QObject *parent) : Utils::TreeModel(parent), m_widthOfLineNumber(0), - m_maxWidthOfFileName(0) + m_maxWidthOfFileName(0), + m_disabled(0) { } @@ -140,6 +141,8 @@ void TestResultModel::addTestResult(TestResult *testResult, bool autoExpand) // we'll add the new item, so raising it's counter if (!isCurrentTestMssg) { int count = m_testResultCount.value(testResult->result(), 0); + if (testResult->result() == Result::MessageDisabledTests) + m_disabled += testResult->line(); m_testResultCount.insert(testResult->result(), ++count); } else { // MessageCurrentTest should always be the last top level item @@ -205,6 +208,7 @@ void TestResultModel::clearTestResults() { clear(); m_testResultCount.clear(); + m_disabled = 0; m_processedIndices.clear(); m_maxWidthOfFileName = 0; m_widthOfLineNumber = 0; diff --git a/plugins/autotest/testresultmodel.h b/plugins/autotest/testresultmodel.h index 5a108aa45ca..782f7223b3e 100644 --- a/plugins/autotest/testresultmodel.h +++ b/plugins/autotest/testresultmodel.h @@ -62,11 +62,13 @@ public: int maxWidthOfLineNumber(const QFont &font); int resultTypeCount(Result::Type type) const { return m_testResultCount.value(type, 0); } + int disabledTests() const { return m_disabled; } private: QMap m_testResultCount; int m_widthOfLineNumber; int m_maxWidthOfFileName; + int m_disabled; QList m_processedIndices; QFont m_measurementFont; }; diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index acd60274788..42886027fc2 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -445,6 +445,10 @@ void TestResultsPane::updateSummaryLabel() labelText.append(QString::fromLatin1(", %1 %2") .arg(QString::number(count), tr("blacklisted"))); + count = m_model->disabledTests(); + if (count) + labelText.append(tr(", %1 disabled").arg(count)); + labelText.append(QLatin1String(".

")); m_summaryLabel->setText(labelText); } From 059f8cf3e9c733f1784f8ccdcd3997d03f01f69f Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 12 Jan 2016 13:48:25 +0100 Subject: [PATCH 175/200] Remove unused variables Change-Id: I54702e7a604c7d450a6664812fb302b9e55f9a47 Reviewed-by: Niels Weber --- plugins/autotest/testrunner.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 7c613984bd6..eae29bec951 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -110,14 +110,10 @@ void performTestRun(QFutureInterface &futureInterface, const QString metricsOption, TestRunner* testRunner) { int testCaseCount = 0; - bool hasQtTests = false; - bool hasGTests = false; foreach (TestConfiguration *config, selectedTests) { config->completeTestInformation(); if (config->project()) { testCaseCount += config->testCaseCount(); - hasQtTests |= config->testType() == TestConfiguration::Qt; - hasGTests |= config->testType() == TestConfiguration::GTest; } else { emitTestResultCreated(new FaultyTestResult(Result::MessageWarn, QObject::tr("Project is null for \"%1\". Removing from test run.\n" From 07ba6bc7e319d868e344021267265c515e1032c9 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 12 Jan 2016 17:53:13 +0100 Subject: [PATCH 176/200] Redo processing output to avoid costly functions Change-Id: I8fa0a84f49b981909d5ac61ef7993c3569aafa2b Reviewed-by: Joerg Bornemann --- plugins/autotest/testoutputreader.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/plugins/autotest/testoutputreader.cpp b/plugins/autotest/testoutputreader.cpp index c75260ef015..df4083b3083 100644 --- a/plugins/autotest/testoutputreader.cpp +++ b/plugins/autotest/testoutputreader.cpp @@ -324,16 +324,22 @@ void TestOutputReader::processGTestOutput() static QString description; static QByteArray unprocessed; - while (m_testApplication->canReadLine()) - unprocessed.append(m_testApplication->readLine()); - - int lineBreak; - while ((lineBreak = unprocessed.indexOf('\n')) != -1) { - const QString line = QLatin1String(unprocessed.left(lineBreak)); - unprocessed.remove(0, lineBreak + 1); - if (line.isEmpty()) { + while (m_testApplication->canReadLine()) { + QByteArray read = m_testApplication->readLine(); + if (!unprocessed.isEmpty()) { + read = unprocessed + read; + unprocessed.clear(); + } + if (!read.endsWith('\n')) { + unprocessed = read; continue; } + read.chop(1); // remove the newline from the output + + const QString line = QString::fromLatin1(read); + if (line.trimmed().isEmpty()) + continue; + if (!line.startsWith(QLatin1Char('['))) { description.append(line).append(QLatin1Char('\n')); if (line.startsWith(QStringLiteral("Note:"))) { From 97011c69510d261b89ce4ac9f595932267328b29 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 12 Jan 2016 13:19:41 +0100 Subject: [PATCH 177/200] Rename setProfile to setProFile Function sets the path to a *.pro file not a profile. Change-Id: Ied804df48086695773e25b63a4bd17c76919b01d Reviewed-by: Niels Weber --- plugins/autotest/testcodeparser.cpp | 10 +++++----- plugins/autotest/testinfo.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index dea7d886be4..8785a55d105 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -970,7 +970,7 @@ void TestCodeParser::updateModelAndCppDocMap(CPlusPlus::Document::Ptr document, const bool setReferencingFile = (files.size() == 2 && file == declaringFile); TestInfo testInfo(testCaseName, testItem->getChildNames(), document->revision(), document->editorRevision()); - testInfo.setProfile(proFile); + testInfo.setProFile(proFile); if (setReferencingFile) testInfo.setReferencingFile(fileName); m_cppDocMap.insert(file, testInfo); @@ -980,7 +980,7 @@ void TestCodeParser::updateModelAndCppDocMap(CPlusPlus::Document::Ptr document, emit testItemCreated(testItem, TestTreeModel::AutoTest); TestInfo ti(testCaseName, testItem->getChildNames(), document->revision(), document->editorRevision()); - ti.setProfile(proFile); + ti.setProFile(proFile); m_cppDocMap.insert(fileName, ti); if (declaringFile != fileName) { ti.setReferencingFile(fileName); @@ -1003,7 +1003,7 @@ void TestCodeParser::updateModelAndQuickDocMap(QmlJS::Document::Ptr document, if (m_quickDocMap.contains(fileName)) { TestInfo testInfo(testItem->name(), testItem->getChildNames(), 0, document->editorRevision()); testInfo.setReferencingFile(referencingFile); - testInfo.setProfile(proFile); + testInfo.setProFile(proFile); emit testItemModified(testItem, TestTreeModel::QuickTest, { fileName }); m_quickDocMap.insert(fileName, testInfo); } else { @@ -1013,7 +1013,7 @@ void TestCodeParser::updateModelAndQuickDocMap(QmlJS::Document::Ptr document, const QString &filePath = testItem->filePath(); TestInfo testInfo(testItem->name(), testItem->getChildNames(), 0, document->editorRevision()); testInfo.setReferencingFile(referencingFile); - testInfo.setProfile(proFile); + testInfo.setProFile(proFile); emit testItemCreated(testItem, TestTreeModel::QuickTest); m_quickDocMap.insert(filePath, testInfo); } @@ -1034,7 +1034,7 @@ void TestCodeParser::updateGTests(const CPlusPlus::Document::Ptr &doc, foreach (const QString &testName, tests.keys()) { TestTreeItem *item = constructGTestTreeItem(fileName, testName, proFile, tests.value(testName)); TestInfo info(item->name(), item->getChildNames(), doc->revision(), doc->editorRevision()); - info.setProfile(proFile); + info.setProFile(proFile); foreach (const TestCodeLocationAndType &testSet, tests.value(testName)) { GTestInfo gtestInfo(testName, testSet.m_name, fileName); if (testSet.m_type == TestTreeItem::GTestNameDisabled) diff --git a/plugins/autotest/testinfo.h b/plugins/autotest/testinfo.h index 374102ed204..056f019a9bb 100644 --- a/plugins/autotest/testinfo.h +++ b/plugins/autotest/testinfo.h @@ -44,7 +44,7 @@ public: const QString referencingFile() const { return m_referencingFile; } void setReferencingFile(const QString &refFile) { m_referencingFile = refFile; } const QString proFile() const { return m_proFile; } - void setProfile(const QString &proFile) { m_proFile = proFile; } + void setProFile(const QString &proFile) { m_proFile = proFile; } private: QString m_className; From 54d753574e84f3b2aeb86027e9875bc477fd6f90 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 12 Jan 2016 13:52:21 +0100 Subject: [PATCH 178/200] Move TestType enum into constants... ...to avoid defining the enum in several places although almost having the same meaning. Additionally rename the values to ensure not to run in a name clash at some point. Change-Id: I0f23041b785c87efd3e7feebef855042595473f6 Reviewed-by: Niels Weber --- plugins/autotest/autotestconstants.h | 12 +++++++++++- plugins/autotest/testconfiguration.cpp | 2 +- plugins/autotest/testconfiguration.h | 7 ++----- plugins/autotest/testresult.cpp | 4 ++-- plugins/autotest/testresult.h | 8 ++------ plugins/autotest/testresultdelegate.cpp | 4 ++-- plugins/autotest/testrunner.cpp | 8 ++++---- plugins/autotest/testtreemodel.cpp | 8 ++++---- 8 files changed, 28 insertions(+), 25 deletions(-) diff --git a/plugins/autotest/autotestconstants.h b/plugins/autotest/autotestconstants.h index ed9c4951493..04b4ac04247 100644 --- a/plugins/autotest/autotestconstants.h +++ b/plugins/autotest/autotestconstants.h @@ -36,8 +36,18 @@ const char TASK_PARSE[] = "AutoTest.Task.Parse"; const char UNNAMED_QUICKTESTS[] = QT_TR_NOOP(""); const char AUTOTEST_SETTINGS_CATEGORY[] = "ZY.Tests"; -} // namespace Autotest } // namespace Constants +namespace Internal { + +enum TestType +{ + TestTypeQt, + TestTypeGTest +}; + +} // namespace Internal +} // namespace Autotest + #endif // AUTOTESTCONSTANTS_H diff --git a/plugins/autotest/testconfiguration.cpp b/plugins/autotest/testconfiguration.cpp index 3cf60556586..96ceaf2a98f 100644 --- a/plugins/autotest/testconfiguration.cpp +++ b/plugins/autotest/testconfiguration.cpp @@ -43,7 +43,7 @@ TestConfiguration::TestConfiguration(const QString &testClass, const QStringList m_unnamedOnly(false), m_project(0), m_guessedConfiguration(false), - m_type(Qt) + m_type(TestTypeQt) { if (testCases.size() != 0) m_testCaseCount = testCases.size(); diff --git a/plugins/autotest/testconfiguration.h b/plugins/autotest/testconfiguration.h index 1b2d34e0873..7b39ae879cb 100644 --- a/plugins/autotest/testconfiguration.h +++ b/plugins/autotest/testconfiguration.h @@ -20,6 +20,8 @@ #ifndef TESTCONFIGURATION_H #define TESTCONFIGURATION_H +#include "autotestconstants.h" + #include #include @@ -37,11 +39,6 @@ class TestConfiguration : public QObject { Q_OBJECT public: - enum TestType { - Qt, - GTest - }; - explicit TestConfiguration(const QString &testClass, const QStringList &testCases, int testCaseCount = 0, QObject *parent = 0); ~TestConfiguration(); diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp index 5885c1c400a..ba75fb5246e 100644 --- a/plugins/autotest/testresult.cpp +++ b/plugins/autotest/testresult.cpp @@ -37,7 +37,7 @@ TestResult::TestResult(const QString &className) : m_class(className) , m_result(Result::Invalid) , m_line(0) - , m_type(Qt) + , m_type(TestTypeQt) { } @@ -155,7 +155,7 @@ QTestResult::QTestResult(const QString &className) GTestResult::GTestResult(const QString &className) : TestResult(className) { - setTestType(GTest); + setTestType(TestTypeGTest); } } // namespace Internal diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index a6c4f3e32a1..b4226da5728 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -20,6 +20,8 @@ #ifndef TESTRESULT_H #define TESTRESULT_H +#include "autotestconstants.h" + #include #include #include @@ -58,12 +60,6 @@ enum Type { class TestResult { public: - enum TestType - { - Qt, - GTest - }; - TestResult(); TestResult(const QString &className); diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp index a1ca6f9fe43..a9a59b7f34e 100644 --- a/plugins/autotest/testresultdelegate.cpp +++ b/plugins/autotest/testresultdelegate.cpp @@ -48,9 +48,9 @@ QString TestResultDelegate::outputString(const TestResult &testResult, bool sele case Result::UnexpectedPass: case Result::BlacklistedFail: case Result::BlacklistedPass: - if (testResult.type() == TestResult::Qt) + if (testResult.type() == TestTypeQt) output = testResult.className() + QLatin1String("::") + testResult.testCase(); - else // TestResult::GTest + else // TestTypeGTest output = testResult.testCase(); if (!testResult.dataTag().isEmpty()) output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag())); diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index eae29bec951..84d500ccdcf 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -142,8 +142,8 @@ void performTestRun(QFutureInterface &futureInterface, if (connection) QObject::disconnect(connection); - TestConfiguration::TestType testType = testConfiguration->testType(); - if (testType == TestConfiguration::Qt) { + TestType testType = testConfiguration->testType(); + if (testType == TestTypeQt) { connection = QObject::connect(&testProcess, &QProcess::readyRead, &outputReader, &TestOutputReader::processOutput); } else { @@ -166,14 +166,14 @@ void performTestRun(QFutureInterface &futureInterface, continue; } - if (testType == TestConfiguration::Qt) { + if (testType == TestTypeQt) { QStringList argumentList(QLatin1String("-xml")); if (!metricsOption.isEmpty()) argumentList << metricsOption; if (testConfiguration->testCases().count()) argumentList << testConfiguration->testCases(); testProcess.setArguments(argumentList); - } else { // TestConfiguration::GTest + } else { // TestTypeGTest const QStringList &testSets = testConfiguration->testCases(); if (testSets.size()) { QStringList argumentList; diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 507e18da20c..49e2070839d 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -256,7 +256,7 @@ QList TestTreeModel::getAllTestCases() const foundMains.value(proFile)); tc->setProFile(proFile); tc->setProject(project); - tc->setTestType(TestConfiguration::GTest); + tc->setTestType(TestTypeGTest); result << tc; } @@ -398,7 +398,7 @@ QList TestTreeModel::getSelectedTests() const foreach (const QString &proFile, proFilesWithEnabledTestSets.keys()) { TestConfiguration *tc = new TestConfiguration(QString(), proFilesWithEnabledTestSets.value(proFile)); - tc->setTestType(TestConfiguration::GTest); + tc->setTestType(TestTypeGTest); tc->setProFile(proFile); tc->setProject(project); result << tc; @@ -468,7 +468,7 @@ TestConfiguration *TestTreeModel::getTestConfiguration(const TestTreeItem *item) config->setTestCaseCount(childCount); config->setProFile(item->childItem(0)->mainFile()); config->setProject(project); - config->setTestType(TestConfiguration::GTest); + config->setTestType(TestTypeGTest); } break; } @@ -478,7 +478,7 @@ TestConfiguration *TestTreeModel::getTestConfiguration(const TestTreeItem *item) QStringList(parent->name() + QLatin1Char('.') + item->name())); config->setProFile(item->mainFile()); config->setProject(project); - config->setTestType(TestConfiguration::GTest); + config->setTestType(TestTypeGTest); break; } // not supported items From 0502bb3cf7ee53f010cdf0a31acc0ee0e8e06f21 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 5 Jan 2016 14:05:23 +0100 Subject: [PATCH 179/200] Move functions to utils class Change-Id: I8fd3d32b22976a11fd5bc5e3282e2cde0c409349 Reviewed-by: Niels Weber --- plugins/autotest/autotest_utils.h | 32 +++++++++++++++++++++-------- plugins/autotest/testcodeparser.cpp | 8 +++----- plugins/autotest/testvisitor.cpp | 2 +- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/plugins/autotest/autotest_utils.h b/plugins/autotest/autotest_utils.h index a9f1ba45bf6..00a2fced864 100644 --- a/plugins/autotest/autotest_utils.h +++ b/plugins/autotest/autotest_utils.h @@ -22,18 +22,34 @@ #include -namespace AutoTest { +namespace Autotest { namespace Internal { -static bool isGTestMacro(const QString ¯o) +class TestUtils { - static QStringList valid = { - QStringLiteral("TEST"), QStringLiteral("TEST_F"), QStringLiteral("TEST_P") - }; - return valid.contains(macro); -} +public: + static bool isGTestMacro(const QString ¯o) + { + static QStringList valid = { + QStringLiteral("TEST"), QStringLiteral("TEST_F"), QStringLiteral("TEST_P") + }; + return valid.contains(macro); + } + + static bool isQTestMacro(const QByteArray ¯o) + { + static QByteArrayList valid = {"QTEST_MAIN", "QTEST_APPLESS_MAIN", "QTEST_GUILESS_MAIN"}; + return valid.contains(macro); + } + + static bool isQuickTestMacro(const QByteArray ¯o) + { + static const QByteArrayList valid = {"QUICK_TEST_MAIN", "QUICK_TEST_OPENGL_MAIN"}; + return valid.contains(macro); + } +}; } // namespace Internal -} // namespace AutoTest +} // namespace Autotest #endif // AUTOTEST_UTILS_H diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 8785a55d105..8ba6768078b 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -277,14 +277,13 @@ static QString quickTestSrcDir(const CppTools::CppModelManager *cppMM, static QString testClass(const CppTools::CppModelManager *modelManager, CPlusPlus::Document::Ptr &document) { - static const QByteArray qtTestMacros[] = {"QTEST_MAIN", "QTEST_APPLESS_MAIN", "QTEST_GUILESS_MAIN"}; const QList macros = document->macroUses(); foreach (const CPlusPlus::Document::MacroUse ¯o, macros) { if (!macro.isFunctionLike()) continue; const QByteArray name = macro.macro().name(); - if (name == qtTestMacros[0] || name == qtTestMacros[1] || name == qtTestMacros[2]) { + if (TestUtils::isQTestMacro(name)) { const CPlusPlus::Document::Block arg = macro.arguments().at(0); return QLatin1String(getFileContent(document->fileName()) .mid(arg.bytesBegin(), arg.bytesEnd() - arg.bytesBegin())); @@ -303,14 +302,13 @@ static QString testClass(const CppTools::CppModelManager *modelManager, static QString quickTestName(const CPlusPlus::Document::Ptr &doc) { - static const QByteArray qtTestMacros[] = {"QUICK_TEST_MAIN", "QUICK_TEST_OPENGL_MAIN"}; const QList macros = doc->macroUses(); foreach (const CPlusPlus::Document::MacroUse ¯o, macros) { if (!macro.isFunctionLike()) continue; const QByteArray name = macro.macro().name(); - if (name == qtTestMacros[0] || name == qtTestMacros[1] || name == qtTestMacros[2]) { + if (TestUtils::isQuickTestMacro(name)) { CPlusPlus::Document::Block arg = macro.arguments().at(0); return QLatin1String(getFileContent(doc->fileName()) .mid(arg.bytesBegin(), arg.bytesEnd() - arg.bytesBegin())); @@ -325,7 +323,7 @@ static QSet testNames(CPlusPlus::Document::Ptr &document) foreach (const CPlusPlus::Document::MacroUse ¯o, document->macroUses()) { if (!macro.isFunctionLike()) continue; - if (AutoTest::Internal::isGTestMacro(QLatin1String(macro.macro().name()))) { + if (TestUtils::isGTestMacro(QLatin1String(macro.macro().name()))) { const QVector args = macro.arguments(); if (args.size() != 2) continue; diff --git a/plugins/autotest/testvisitor.cpp b/plugins/autotest/testvisitor.cpp index 9a0c51961d6..67fdecd6092 100644 --- a/plugins/autotest/testvisitor.cpp +++ b/plugins/autotest/testvisitor.cpp @@ -359,7 +359,7 @@ bool GTestVisitor::visit(CPlusPlus::FunctionDefinitionAST *ast) CPlusPlus::LookupContext lc; const QString prettyName = m_overview.prettyName(lc.fullyQualifiedName(ast->symbol)); - if (!AutoTest::Internal::isGTestMacro(prettyName)) + if (!TestUtils::isGTestMacro(prettyName)) return false; CPlusPlus::Argument *testCaseNameArg = ast->symbol->argumentAt(0)->asArgument(); From 2b414536a0de67c0dec127065195c0a102f6ccf3 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Wed, 13 Jan 2016 12:14:43 +0100 Subject: [PATCH 180/200] Fix compile break Add cpptools/projectinfo.h Change-Id: I270005c56dd1a02941e5d728c712b29830507acb Reviewed-by: Nikolai Kosjar --- plugins/autotest/autotestunittests.cpp | 1 + plugins/autotest/testconfiguration.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/plugins/autotest/autotestunittests.cpp b/plugins/autotest/autotestunittests.cpp index 1a8097c48ca..c80aae964eb 100644 --- a/plugins/autotest/autotestunittests.cpp +++ b/plugins/autotest/autotestunittests.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include diff --git a/plugins/autotest/testconfiguration.cpp b/plugins/autotest/testconfiguration.cpp index 96ceaf2a98f..dd8a2c3b066 100644 --- a/plugins/autotest/testconfiguration.cpp +++ b/plugins/autotest/testconfiguration.cpp @@ -20,6 +20,7 @@ #include "testconfiguration.h" #include +#include #include #include From cbdf48a7928425b096815f6254c01db6b8c3b420 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 12 Jan 2016 16:45:20 +0100 Subject: [PATCH 181/200] Distinguish between parameterized and unparameterized google tests This additionally fixes an issue when trying to execute a parameterized google test by invoking 'Run This Test' or using 'Run Selected Tests'. Change-Id: I199effcf76b34efd1a041c9a38b5bf90cdc002f8 Reviewed-by: Niels Weber --- plugins/autotest/autotest_utils.h | 5 +++ plugins/autotest/testcodeparser.cpp | 39 +++++++++++------------ plugins/autotest/testcodeparser.h | 5 +-- plugins/autotest/testnavigationwidget.cpp | 2 ++ plugins/autotest/testtreeitem.cpp | 8 +++-- plugins/autotest/testtreeitem.h | 3 +- plugins/autotest/testtreemodel.cpp | 33 ++++++++++++++----- plugins/autotest/testvisitor.cpp | 5 ++- plugins/autotest/testvisitor.h | 17 ++++++++-- 9 files changed, 80 insertions(+), 37 deletions(-) diff --git a/plugins/autotest/autotest_utils.h b/plugins/autotest/autotest_utils.h index 00a2fced864..ee3c464c6a2 100644 --- a/plugins/autotest/autotest_utils.h +++ b/plugins/autotest/autotest_utils.h @@ -36,6 +36,11 @@ public: return valid.contains(macro); } + static bool isGTestParameterized(const QString ¯o) + { + return macro == QStringLiteral("TEST_P"); + } + static bool isQTestMacro(const QByteArray ¯o) { static QByteArrayList valid = {"QTEST_MAIN", "QTEST_APPLESS_MAIN", "QTEST_GUILESS_MAIN"}; diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 8ba6768078b..af48f475682 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -317,9 +317,8 @@ static QString quickTestName(const CPlusPlus::Document::Ptr &doc) return QString(); } -static QSet testNames(CPlusPlus::Document::Ptr &document) +static bool hasGTestNames(CPlusPlus::Document::Ptr &document) { - QSet result; foreach (const CPlusPlus::Document::MacroUse ¯o, document->macroUses()) { if (!macro.isFunctionLike()) continue; @@ -327,12 +326,10 @@ static QSet testNames(CPlusPlus::Document::Ptr &document) const QVector args = macro.arguments(); if (args.size() != 2) continue; - const CPlusPlus::Document::Block name = args.first(); - result.insert(QLatin1String(getFileContent(document->fileName()) - .mid(name.bytesBegin(), name.bytesEnd() - name.bytesBegin()))); + return true; } } - return result; + return false; } static QList scanDirectoryForQuickTestQmlFiles(const QString &srcDir) @@ -457,12 +454,14 @@ static TestTreeItem *constructTestTreeItem(const QString &fileName, return treeItem; } -static TestTreeItem *constructGTestTreeItem(const QString &filePath, const QString &caseName, +static TestTreeItem *constructGTestTreeItem(const QString &filePath, const GTestCaseSpec &caseSpec, const QString &proFile, - const TestCodeLocationList &testNames) + const TestCodeLocationList &testSets) { - TestTreeItem *item = new TestTreeItem(caseName, QString(), TestTreeItem::GTestCase); - foreach (const TestCodeLocationAndType &locationAndType, testNames) { + TestTreeItem *item = new TestTreeItem(caseSpec.testCaseName, QString(), + caseSpec.parameterized ? TestTreeItem::GTestCaseParameterized + : TestTreeItem::GTestCase); + foreach (const TestCodeLocationAndType &locationAndType, testSets) { TestTreeItem *treeItemChild = new TestTreeItem(locationAndType.m_name, filePath, locationAndType.m_type); treeItemChild->setLine(locationAndType.m_line); @@ -549,9 +548,8 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr document) } if (includesGTest(document, modelManager)) { - const QSet &names = testNames(document); - if (!names.isEmpty()) { - handleGTest(document->fileName(), names); + if (hasGTestNames(document)) { + handleGTest(document->fileName()); return; } } @@ -609,7 +607,7 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr document) } } -void TestCodeParser::handleGTest(const QString &filePath, const QSet &names) +void TestCodeParser::handleGTest(const QString &filePath) { const QByteArray &fileContent = getFileContent(filePath); const CPlusPlus::Snapshot snapshot = CPlusPlus::CppModelManagerBase::instance()->snapshot(); @@ -619,8 +617,7 @@ void TestCodeParser::handleGTest(const QString &filePath, const QSet &n GTestVisitor visitor(document); visitor.accept(ast); - QMap result = visitor.gtestFunctions(); - QTC_CHECK(names.contains(result.keys().toSet())); + QMap result = visitor.gtestFunctions(); updateGTests(document, result); } @@ -1018,7 +1015,7 @@ void TestCodeParser::updateModelAndQuickDocMap(QmlJS::Document::Ptr document, } void TestCodeParser::updateGTests(const CPlusPlus::Document::Ptr &doc, - const QMap &tests) + const QMap &tests) { const QString &fileName = doc->fileName(); removeGTestsByName(fileName); @@ -1029,12 +1026,12 @@ void TestCodeParser::updateGTests(const CPlusPlus::Document::Ptr &doc, if (ppList.size()) proFile = ppList.at(0)->projectFile; - foreach (const QString &testName, tests.keys()) { - TestTreeItem *item = constructGTestTreeItem(fileName, testName, proFile, tests.value(testName)); + foreach (const GTestCaseSpec &testSpec, tests.keys()) { + TestTreeItem *item = constructGTestTreeItem(fileName, testSpec, proFile, tests.value(testSpec)); TestInfo info(item->name(), item->getChildNames(), doc->revision(), doc->editorRevision()); info.setProFile(proFile); - foreach (const TestCodeLocationAndType &testSet, tests.value(testName)) { - GTestInfo gtestInfo(testName, testSet.m_name, fileName); + foreach (const TestCodeLocationAndType &testSet, tests.value(testSpec)) { + GTestInfo gtestInfo(testSpec.testCaseName, testSet.m_name, fileName); if (testSet.m_type == TestTreeItem::GTestNameDisabled) gtestInfo.setEnabled(false); m_gtestDocList.append(gtestInfo); diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 2889b5a041a..ef2c555ba94 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -41,6 +41,7 @@ struct TestCodeLocationAndType; class TestInfo; class UnnamedQuickTestInfo; class GTestInfo; +struct GTestCaseSpec; class TestCodeParser : public QObject { @@ -84,7 +85,7 @@ public slots: void updateTestTree(); void checkDocumentForTestCode(CPlusPlus::Document::Ptr document); void handleQtQuickTest(CPlusPlus::Document::Ptr document); - void handleGTest(const QString &filePath, const QSet &names); + void handleGTest(const QString &filePath); void onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document); void onQmlDocumentUpdated(const QmlJS::Document::Ptr &document); @@ -109,7 +110,7 @@ private: void updateModelAndQuickDocMap(QmlJS::Document::Ptr document, const QString &referencingFile, TestTreeItem *testItem); void updateGTests(const CPlusPlus::Document::Ptr &doc, - const QMap &tests); + const QMap &tests); void removeUnnamedQuickTestsByName(const QString &fileName); void removeGTestsByName(const QString &fileName); diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index bff1b4de8d6..914290e36b9 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -108,6 +108,7 @@ void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event) || (type == TestTreeItem::TestClass && index.data().toString() != unnamed) || (type == TestTreeItem::TestDataTag) || (type == TestTreeItem::GTestCase) + || (type == TestTreeItem::GTestCaseParameterized) || (type == TestTreeItem::GTestName)) { runThisTest = new QAction(tr("Run This Test"), &menu); runThisTest->setEnabled(enabled); @@ -255,6 +256,7 @@ void TestNavigationWidget::onRunThisTestTriggered() if (item->type() == TestTreeItem::TestClass || item->type() == TestTreeItem::TestFunction || item->type() == TestTreeItem::TestDataTag || item->type() == TestTreeItem::GTestCase + || item->type() == TestTreeItem::GTestCaseParameterized || item->type() == TestTreeItem::GTestName) { if (TestConfiguration *configuration = m_model->getTestConfiguration(item)) { TestRunner *runner = TestRunner::instance(); diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index afba068ac47..59318bda5e8 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -40,6 +40,7 @@ TestTreeItem::TestTreeItem(const QString &name, const QString &filePath, Type ty case TestClass: case TestFunction: case GTestCase: + case GTestCaseParameterized: case GTestName: case GTestNameDisabled: m_checked = Qt::Checked; @@ -76,7 +77,7 @@ static QIcon testTreeIcon(TestTreeItem::Type type) QIcon(QLatin1String(":/images/func.png")), QIcon(QLatin1String(":/images/data.png")) }; - if (type == TestTreeItem::GTestCase) + if (type == TestTreeItem::GTestCase || type == TestTreeItem::GTestCaseParameterized) return icons[1]; if (int(type) >= int(sizeof icons / sizeof *icons)) @@ -111,6 +112,7 @@ QVariant TestTreeItem::data(int /*column*/, int role) const return QVariant(); case TestClass: case GTestCase: + case GTestCaseParameterized: return m_name.isEmpty() ? QVariant() : checked(); case TestFunction: case GTestName: @@ -191,7 +193,8 @@ void TestTreeItem::setChecked(const Qt::CheckState checkState) break; } case TestClass: - case GTestCase: { + case GTestCase: + case GTestCaseParameterized: { Qt::CheckState usedState = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked); for (int row = 0, count = childCount(); row < count; ++row) childItem(row)->setChecked(usedState); @@ -208,6 +211,7 @@ Qt::CheckState TestTreeItem::checked() const case TestClass: case TestFunction: case GTestCase: + case GTestCaseParameterized: case GTestName: case GTestNameDisabled: return m_checked; diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index dbd9b4a8ab4..ac4134ee36a 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -48,7 +48,8 @@ public: TestDataTag, TestDataFunction, TestSpecialFunction, - GTestCase, // should we distinguish between Case and Fixture? + GTestCase, + GTestCaseParameterized, GTestName, GTestNameDisabled }; diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 49e2070839d..e79d2325e98 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -140,6 +140,7 @@ bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int switch (item->type()) { case TestTreeItem::TestClass: case TestTreeItem::GTestCase: + case TestTreeItem::GTestCaseParameterized: if (item->childCount() > 0) emit dataChanged(index.child(0, 0), index.child(item->childCount() - 1, 0)); break; @@ -166,6 +167,7 @@ Qt::ItemFlags TestTreeModel::flags(const QModelIndex &index) const switch(item->type()) { case TestTreeItem::TestClass: case TestTreeItem::GTestCase: + case TestTreeItem::GTestCaseParameterized: if (item->name().isEmpty()) return Qt::ItemIsEnabled | Qt::ItemIsSelectable; return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsTristate | Qt::ItemIsUserCheckable; @@ -389,8 +391,14 @@ QList TestTreeModel::getSelectedTests() const const TestTreeItem *grandChild = child->childItem(grandChildRow); const QString &proFile = grandChild->mainFile(); QStringList enabled = proFilesWithEnabledTestSets.value(proFile); - if (grandChild->checked() == Qt::Checked) - enabled << child->name() + QLatin1Char('.') + grandChild->name(); + if (grandChild->checked() == Qt::Checked) { + QString testSpecifier = child->name() + QLatin1Char('.') + grandChild->name(); + if (child->type() == TestTreeItem::GTestCaseParameterized) { + testSpecifier.prepend(QLatin1String("*/")); + testSpecifier.append(QLatin1String("/*")); + } + enabled << testSpecifier; + } proFilesWithEnabledTestSets.insert(proFile, enabled); } } @@ -461,10 +469,14 @@ TestConfiguration *TestTreeModel::getTestConfiguration(const TestTreeItem *item) config->setProject(project); break; } - case TestTreeItem::GTestCase: { + case TestTreeItem::GTestCase: + case TestTreeItem::GTestCaseParameterized: { + QString testSpecifier = item->name() + QLatin1String(".*"); + if (item->type() == TestTreeItem::GTestCaseParameterized) + testSpecifier.prepend(QLatin1String("*/")); + if (int childCount = item->childCount()) { - config = new TestConfiguration(QString(), - QStringList(item->name() + QLatin1String(".*"))); + config = new TestConfiguration(QString(), QStringList(testSpecifier)); config->setTestCaseCount(childCount); config->setProFile(item->childItem(0)->mainFile()); config->setProject(project); @@ -474,8 +486,13 @@ TestConfiguration *TestTreeModel::getTestConfiguration(const TestTreeItem *item) } case TestTreeItem::GTestName: { const TestTreeItem *parent = item->parentItem(); - config = new TestConfiguration(QString(), - QStringList(parent->name() + QLatin1Char('.') + item->name())); + QString testSpecifier = parent->name() + QLatin1Char('.') + item->name(); + + if (parent->type() == TestTreeItem::GTestCaseParameterized) { + testSpecifier.prepend(QLatin1String("*/")); + testSpecifier.append(QLatin1String("/*")); + } + config = new TestConfiguration(QString(), QStringList(testSpecifier)); config->setProFile(item->mainFile()); config->setProject(project); config->setTestType(TestTypeGTest); @@ -578,7 +595,7 @@ void TestTreeModel::addTestTreeItem(TestTreeItem *item, TestTreeModel::Type type TestTreeItem *toBeUpdated = 0; for (int row = 0, count = parent->childCount(); row < count; ++row) { TestTreeItem *current = parent->childItem(row); - if (current->name() == item->name()) { + if (current->name() == item->name() && current->type() == item->type()) { toBeUpdated = current; break; } diff --git a/plugins/autotest/testvisitor.cpp b/plugins/autotest/testvisitor.cpp index 67fdecd6092..9c4d4d272d8 100644 --- a/plugins/autotest/testvisitor.cpp +++ b/plugins/autotest/testvisitor.cpp @@ -380,7 +380,10 @@ bool GTestVisitor::visit(CPlusPlus::FunctionDefinitionAST *ast) locationAndType.m_column = column - 1; locationAndType.m_type = disabled ? TestTreeItem::GTestNameDisabled : TestTreeItem::GTestName; - m_gtestFunctions[testCaseName].append(locationAndType); + GTestCaseSpec spec; + spec.testCaseName = testCaseName; + spec.parameterized = TestUtils::isGTestParameterized(prettyName); + m_gtestFunctions[spec].append(locationAndType); } return false; diff --git a/plugins/autotest/testvisitor.h b/plugins/autotest/testvisitor.h index bbccffd4e18..ec01686b6b9 100644 --- a/plugins/autotest/testvisitor.h +++ b/plugins/autotest/testvisitor.h @@ -123,18 +123,31 @@ private: }; +struct GTestCaseSpec +{ + QString testCaseName; + bool parameterized; +}; + +inline bool operator<(const GTestCaseSpec &spec1, const GTestCaseSpec &spec2) +{ + if (spec1.testCaseName != spec2.testCaseName) + return spec1.testCaseName < spec2.testCaseName; + return !spec1.parameterized; +} + class GTestVisitor : public CPlusPlus::ASTVisitor { public: GTestVisitor(CPlusPlus::Document::Ptr doc); bool visit(CPlusPlus::FunctionDefinitionAST *ast); - QMap gtestFunctions() const { return m_gtestFunctions; } + QMap gtestFunctions() const { return m_gtestFunctions; } private: CPlusPlus::Document::Ptr m_document; CPlusPlus::Overview m_overview; - QMap m_gtestFunctions; + QMap m_gtestFunctions; }; From 1abd193bb24669b90533feb7a579ac56d58936ff Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 15 Jan 2016 06:38:42 +0100 Subject: [PATCH 182/200] Fix operator<() for GTestCaseSpec Introduced broken with cbdf48a7928425b096815f6254c01db6b8c3b420. Change-Id: Ib224fd167573594673f5370c5330280809017904 Reviewed-by: Niels Weber --- plugins/autotest/testvisitor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/autotest/testvisitor.h b/plugins/autotest/testvisitor.h index ec01686b6b9..c2129d3f1d2 100644 --- a/plugins/autotest/testvisitor.h +++ b/plugins/autotest/testvisitor.h @@ -133,7 +133,7 @@ inline bool operator<(const GTestCaseSpec &spec1, const GTestCaseSpec &spec2) { if (spec1.testCaseName != spec2.testCaseName) return spec1.testCaseName < spec2.testCaseName; - return !spec1.parameterized; + return spec1.parameterized == spec2.parameterized ? false : !spec1.parameterized; } class GTestVisitor : public CPlusPlus::ASTVisitor From 02281ad4294f1f3e91c9c63de7b048f09b068e75 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 10 Dec 2015 13:46:04 +0100 Subject: [PATCH 183/200] Provide plugin unit test for gtest code parsing This test needs environment variable GOOGLETEST_DIR to point to an existing checkout of the googletest repository, or it will be skipped. Change-Id: I1e0ba250da84143b50f70589113ab6d6ea3a5b73 Reviewed-by: Niels Weber --- plugins/autotest/autotestunittests.cpp | 41 +++++++++++ plugins/autotest/autotestunittests.h | 1 + plugins/autotest/autotestunittests.qrc | 11 +++ plugins/autotest/testcodeparser.cpp | 5 ++ plugins/autotest/testcodeparser.h | 1 + plugins/autotest/testtreemodel.cpp | 18 +++++ plugins/autotest/testtreemodel.h | 2 + .../unit_test/simple_gt/simple_gt.pro | 5 ++ .../autotest/unit_test/simple_gt/src/main.cpp | 6 ++ .../autotest/unit_test/simple_gt/src/src.pro | 9 +++ .../unit_test/simple_gt/tests/gt1/further.cpp | 42 +++++++++++ .../unit_test/simple_gt/tests/gt1/gt1.pro | 10 +++ .../unit_test/simple_gt/tests/gt1/main.cpp | 71 +++++++++++++++++++ .../unit_test/simple_gt/tests/gt2/gt2.pro | 12 ++++ .../unit_test/simple_gt/tests/gt2/main.cpp | 48 +++++++++++++ .../unit_test/simple_gt/tests/gt2/queuetest.h | 32 +++++++++ .../simple_gt/tests/gtest_dependency.pri | 25 +++++++ .../unit_test/simple_gt/tests/tests.pro | 4 ++ 18 files changed, 343 insertions(+) create mode 100644 plugins/autotest/unit_test/simple_gt/simple_gt.pro create mode 100644 plugins/autotest/unit_test/simple_gt/src/main.cpp create mode 100644 plugins/autotest/unit_test/simple_gt/src/src.pro create mode 100644 plugins/autotest/unit_test/simple_gt/tests/gt1/further.cpp create mode 100644 plugins/autotest/unit_test/simple_gt/tests/gt1/gt1.pro create mode 100644 plugins/autotest/unit_test/simple_gt/tests/gt1/main.cpp create mode 100644 plugins/autotest/unit_test/simple_gt/tests/gt2/gt2.pro create mode 100644 plugins/autotest/unit_test/simple_gt/tests/gt2/main.cpp create mode 100644 plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h create mode 100644 plugins/autotest/unit_test/simple_gt/tests/gtest_dependency.pri create mode 100644 plugins/autotest/unit_test/simple_gt/tests/tests.pro diff --git a/plugins/autotest/autotestunittests.cpp b/plugins/autotest/autotestunittests.cpp index c80aae964eb..9582a23c68e 100644 --- a/plugins/autotest/autotestunittests.cpp +++ b/plugins/autotest/autotestunittests.cpp @@ -189,5 +189,46 @@ void AutoTestUnitTests::testCodeParserSwitchStartup_data() << expectedUnnamedQuickTests << expectedDataTagsCount; } +void AutoTestUnitTests::testCodeParserGTest() +{ + if (qgetenv("GOOGLETEST_DIR").isEmpty()) + QSKIP("This test needs googletest - set GOOGLETEST_DIR (point to googletest repository)"); + + NavigationWidget *navigation = NavigationWidget::instance(); + navigation->activateSubWidget(Constants::AUTOTEST_ID); + + CppTools::Tests::ProjectOpenerAndCloser projectManager; + CppTools::ProjectInfo projectInfo = projectManager.open( + QString(m_tmpDir->path() + QLatin1String("/simple_gt/simple_gt.pro")), true); + QVERIFY(projectInfo.isValid()); + + QSignalSpy parserSpy(m_model->parser(), SIGNAL(parsingFinished())); + QVERIFY(parserSpy.wait(20000)); + + QCOMPARE(m_model->gtestNamesCount(), 4); + QCOMPARE(m_model->parser()->gtestNamesAndSetsCount(), 9); // 9 == 3 + 2 + 2 + 2, see below + + QMap expectedNamesAndSets; + expectedNamesAndSets.insert(QStringLiteral("FactorialTest"), 3); + expectedNamesAndSets.insert(QStringLiteral("FactorialTest_Iterative"), 2); + expectedNamesAndSets.insert(QStringLiteral("Sum"), 2); + expectedNamesAndSets.insert(QStringLiteral("QueueTest"), 2); + + QMap foundNamesAndSets = m_model->gtestNamesAndSets(); + QCOMPARE(expectedNamesAndSets.size(), foundNamesAndSets.size()); + foreach (const QString &name, expectedNamesAndSets.keys()) + QCOMPARE(expectedNamesAndSets.value(name), foundNamesAndSets.value(name)); + + // check also that no Qt related tests have been found + QCOMPARE(m_model->autoTestsCount(), 0); + QCOMPARE(m_model->namedQuickTestsCount(), 0); + QCOMPARE(m_model->unnamedQuickTestsCount(), 0); + QCOMPARE(m_model->dataTagsCount(), 0); + + QCOMPARE(m_model->parser()->autoTestsCount(), 0); + QCOMPARE(m_model->parser()->namedQuickTestsCount(), 0); + QCOMPARE(m_model->parser()->unnamedQuickTestsCount(), 0); +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/autotestunittests.h b/plugins/autotest/autotestunittests.h index e359e4175dc..ddd5249739c 100644 --- a/plugins/autotest/autotestunittests.h +++ b/plugins/autotest/autotestunittests.h @@ -45,6 +45,7 @@ private slots: void testCodeParser_data(); void testCodeParserSwitchStartup(); void testCodeParserSwitchStartup_data(); + void testCodeParserGTest(); private: TestTreeModel *m_model; diff --git a/plugins/autotest/autotestunittests.qrc b/plugins/autotest/autotestunittests.qrc index 25ce4044feb..96e5b05a31a 100644 --- a/plugins/autotest/autotestunittests.qrc +++ b/plugins/autotest/autotestunittests.qrc @@ -39,5 +39,16 @@ unit_test/mixed_atp/tests/auto/gui/gui.qbs unit_test/mixed_atp/tests/auto/quickauto/quickauto.qbs unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs + unit_test/simple_gt/src/main.cpp + unit_test/simple_gt/src/src.pro + unit_test/simple_gt/tests/gt1/further.cpp + unit_test/simple_gt/tests/gt1/gt1.pro + unit_test/simple_gt/tests/gt1/main.cpp + unit_test/simple_gt/tests/gt2/gt2.pro + unit_test/simple_gt/tests/gt2/main.cpp + unit_test/simple_gt/tests/gt2/queuetest.h + unit_test/simple_gt/tests/tests.pro + unit_test/simple_gt/simple_gt.pro + unit_test/simple_gt/tests/gtest_dependency.pri diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index af48f475682..0b73568443f 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -1079,6 +1079,11 @@ int TestCodeParser::unnamedQuickTestsCount() const { return m_unnamedQuickDocList.size(); } + +int TestCodeParser::gtestNamesAndSetsCount() const +{ + return m_gtestDocList.size(); +} #endif } // namespace Internal diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index ef2c555ba94..5861009e5ac 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -64,6 +64,7 @@ public: int autoTestsCount() const; int namedQuickTestsCount() const; int unnamedQuickTestsCount() const; + int gtestNamesAndSetsCount() const; #endif signals: diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index e79d2325e98..b52a768ef2b 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -818,6 +818,24 @@ int TestTreeModel::dataTagsCount() const } return dataTagCount; } + +int TestTreeModel::gtestNamesCount() const +{ + return m_googleTestRootItem ? m_googleTestRootItem->childCount() : 0; +} + +QMap TestTreeModel::gtestNamesAndSets() const +{ + QMap result; + + if (m_googleTestRootItem) { + for (int row = 0, count = m_googleTestRootItem->childCount(); row < count; ++row) { + const TestTreeItem *current = m_googleTestRootItem->childItem(row); + result.insert(current->name(), current->childCount()); + } + } + return result; +} #endif /***************************** Sort/Filter Model **********************************/ diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index bef6ec86f00..2f7f00a4e87 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -69,6 +69,8 @@ public: int namedQuickTestsCount() const; int unnamedQuickTestsCount() const; int dataTagsCount() const; + int gtestNamesCount() const; + QMap gtestNamesAndSets() const; #endif signals: diff --git a/plugins/autotest/unit_test/simple_gt/simple_gt.pro b/plugins/autotest/unit_test/simple_gt/simple_gt.pro new file mode 100644 index 00000000000..9ce665aceff --- /dev/null +++ b/plugins/autotest/unit_test/simple_gt/simple_gt.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs + +SUBDIRS += src \ + tests + diff --git a/plugins/autotest/unit_test/simple_gt/src/main.cpp b/plugins/autotest/unit_test/simple_gt/src/main.cpp new file mode 100644 index 00000000000..25579cd61bc --- /dev/null +++ b/plugins/autotest/unit_test/simple_gt/src/main.cpp @@ -0,0 +1,6 @@ +#include + +int main(int argc, char *argv[]) { + QCoreApplication a(argc, argv); + return a.exec(); +} diff --git a/plugins/autotest/unit_test/simple_gt/src/src.pro b/plugins/autotest/unit_test/simple_gt/src/src.pro new file mode 100644 index 00000000000..03886429244 --- /dev/null +++ b/plugins/autotest/unit_test/simple_gt/src/src.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +CONFIG += qt console +CONFIG -= app_bundle + +QT += core + +SOURCES += main.cpp + diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt1/further.cpp b/plugins/autotest/unit_test/simple_gt/tests/gt1/further.cpp new file mode 100644 index 00000000000..559bde41635 --- /dev/null +++ b/plugins/autotest/unit_test/simple_gt/tests/gt1/further.cpp @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ +#include + +using namespace testing; + +int sum(int a, int b) +{ + return a + b; +} + +TEST(Sum, HandlePositives) +{ + EXPECT_EQ(5, sum(2, 3)); + EXPECT_EQ(5, sum(3, 2)); +} + +TEST(Sum, HandleZero) +{ + EXPECT_EQ(1, sum(0, 0)); +} + +TEST(FactorialTest, DISABLED_Fake) +{ + EXPECT_EQ(-4, sum(-2, -2)); +} diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt1/gt1.pro b/plugins/autotest/unit_test/simple_gt/tests/gt1/gt1.pro new file mode 100644 index 00000000000..1ebd037c070 --- /dev/null +++ b/plugins/autotest/unit_test/simple_gt/tests/gt1/gt1.pro @@ -0,0 +1,10 @@ +include(../gtest_dependency.pri) + +TEMPLATE = app +CONFIG += console c++11 +CONFIG -= app_bundle +CONFIG += thread +CONFIG -= qt + +SOURCES += main.cpp \ + further.cpp diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt1/main.cpp b/plugins/autotest/unit_test/simple_gt/tests/gt1/main.cpp new file mode 100644 index 00000000000..64e386b8862 --- /dev/null +++ b/plugins/autotest/unit_test/simple_gt/tests/gt1/main.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ +#include +#include + +using namespace testing; + +int factorial(int a) +{ + if (a == 0) + return 1; + if (a == 1) + return a; + return a * factorial(a - 1); +} + +int factorial_it(int a) +{ + int result = 1; + for (int i = 2; i <= a; ++i) + result *= i; + return result; +} + +TEST(FactorialTest, HandlesZeroInput) +{ + EXPECT_EQ(1, factorial(0)); +} + +TEST(FactorialTest, HandlesPositiveInput) +{ + ASSERT_EQ(1, factorial(1)); + ASSERT_THAT(factorial(2), Eq(2)); + EXPECT_EQ(6, factorial(3)); + EXPECT_EQ(40320, factorial(8)); +} + +TEST(FactorialTest_Iterative, HandlesZeroInput) +{ + ASSERT_EQ(1, factorial_it(0)); +} + +TEST(FactorialTest_Iterative, DISABLED_HandlesPositiveInput) +{ + ASSERT_EQ(1, factorial_it(1)); + ASSERT_EQ(2, factorial_it(2)); + ASSERT_EQ(6, factorial_it(3)); + ASSERT_EQ(40320, factorial_it(8)); +} + +int main(int argc, char *argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt2/gt2.pro b/plugins/autotest/unit_test/simple_gt/tests/gt2/gt2.pro new file mode 100644 index 00000000000..65796da9abe --- /dev/null +++ b/plugins/autotest/unit_test/simple_gt/tests/gt2/gt2.pro @@ -0,0 +1,12 @@ +include(../gtest_dependency.pri) + +TEMPLATE = app +CONFIG += qt console c++11 +CONFIG -= app_bundle + +HEADERS += \ + queuetest.h + +SOURCES += \ + main.cpp + diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt2/main.cpp b/plugins/autotest/unit_test/simple_gt/tests/gt2/main.cpp new file mode 100644 index 00000000000..2bda4c12d3f --- /dev/null +++ b/plugins/autotest/unit_test/simple_gt/tests/gt2/main.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ +#include +#include + +#include "queuetest.h" + +using namespace testing; + +TEST_F(QueueTest, IsEmptyInitialized) +{ + EXPECT_EQ(0, m_queue0.size()); +} + +TEST_F(QueueTest, DequeueWorks) +{ + ASSERT_FALSE(m_queue1.isEmpty()); + int n = m_queue1.dequeue(); + ASSERT_TRUE(m_queue1.isEmpty()); + EXPECT_EQ(1, n); + + ASSERT_FALSE(m_queue2.isEmpty()); + float f = m_queue2.dequeue(); + ASSERT_TRUE(m_queue2.isEmpty()); + EXPECT_EQ(1.0f, f); +} + +int main(int argc, char *argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h b/plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h new file mode 100644 index 00000000000..aebabf0f336 --- /dev/null +++ b/plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h @@ -0,0 +1,32 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ +#include + +class QueueTest : public ::testing::Test +{ +protected: + virtual void SetUp() { + m_queue1.enqueue(1); + m_queue2.enqueue(1.0f); + } + + QQueue m_queue0; + QQueue m_queue1; + QQueue m_queue2; +}; diff --git a/plugins/autotest/unit_test/simple_gt/tests/gtest_dependency.pri b/plugins/autotest/unit_test/simple_gt/tests/gtest_dependency.pri new file mode 100644 index 00000000000..bd22edc2f20 --- /dev/null +++ b/plugins/autotest/unit_test/simple_gt/tests/gtest_dependency.pri @@ -0,0 +1,25 @@ +isEmpty(GOOGLETEST_DIR):GOOGLETEST_DIR=$$(GOOGLETEST_DIR) + +isEmpty(GOOGLETEST_DIR):linux-* { + GTEST_SRCDIR = /usr/include/gtest + GMOCK_SRCDIR = /usr/include/gmock +} else { + GTEST_SRCDIR = $$GOOGLETEST_DIR/googletest + GMOCK_SRCDIR = $$GOOGLETEST_DIR/googlemock +} + +requires(exists($$GTEST_SRCDIR):exists($$GMOCK_SRCDIR)) +!exists($$GOOGLETEST_DIR):message("No googletest src dir found - set GOOGLETEST_DIR to enable.") + +DEFINES += \ + GTEST_LANG_CXX11 + +INCLUDEPATH *= \ + $$GTEST_SRCDIR \ + $$GTEST_SRCDIR/include \ + $$GMOCK_SRCDIR \ + $$GMOCK_SRCDIR/include + +SOURCES += \ + $$GTEST_SRCDIR/src/gtest-all.cc \ + $$GMOCK_SRCDIR/src/gmock-all.cc diff --git a/plugins/autotest/unit_test/simple_gt/tests/tests.pro b/plugins/autotest/unit_test/simple_gt/tests/tests.pro new file mode 100644 index 00000000000..77f3621946d --- /dev/null +++ b/plugins/autotest/unit_test/simple_gt/tests/tests.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs + +SUBDIRS += gt1 \ + gt2 From 9055ac5f50f023d6bacb2b6c26cbb5fa7a995503 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 13 Jan 2016 09:10:11 +0100 Subject: [PATCH 184/200] Provide parameterized gtest for plugin unit tests Change-Id: I17a42a9070546a5b461fcb27643bd6db7b5d7b4f Reviewed-by: Niels Weber --- plugins/autotest/autotestunittests.cpp | 13 +-- plugins/autotest/autotestunittests.qrc | 3 + plugins/autotest/testtreemodel.cpp | 4 +- plugins/autotest/testtreemodel.h | 2 +- .../unit_test/simple_gt/tests/gt3/dummytest.h | 37 ++++++++ .../unit_test/simple_gt/tests/gt3/gt3.pro | 12 +++ .../unit_test/simple_gt/tests/gt3/main.cpp | 85 +++++++++++++++++++ .../unit_test/simple_gt/tests/tests.pro | 3 +- 8 files changed, 150 insertions(+), 9 deletions(-) create mode 100644 plugins/autotest/unit_test/simple_gt/tests/gt3/dummytest.h create mode 100644 plugins/autotest/unit_test/simple_gt/tests/gt3/gt3.pro create mode 100644 plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp diff --git a/plugins/autotest/autotestunittests.cpp b/plugins/autotest/autotestunittests.cpp index 9582a23c68e..95bc954502f 100644 --- a/plugins/autotest/autotestunittests.cpp +++ b/plugins/autotest/autotestunittests.cpp @@ -205,19 +205,22 @@ void AutoTestUnitTests::testCodeParserGTest() QSignalSpy parserSpy(m_model->parser(), SIGNAL(parsingFinished())); QVERIFY(parserSpy.wait(20000)); - QCOMPARE(m_model->gtestNamesCount(), 4); - QCOMPARE(m_model->parser()->gtestNamesAndSetsCount(), 9); // 9 == 3 + 2 + 2 + 2, see below + QCOMPARE(m_model->gtestNamesCount(), 6); + // 11 == 3 + 2 + 2 + 2 + 1 + 1, see below + QCOMPARE(m_model->parser()->gtestNamesAndSetsCount(), 11); - QMap expectedNamesAndSets; + QMultiMap expectedNamesAndSets; expectedNamesAndSets.insert(QStringLiteral("FactorialTest"), 3); expectedNamesAndSets.insert(QStringLiteral("FactorialTest_Iterative"), 2); expectedNamesAndSets.insert(QStringLiteral("Sum"), 2); expectedNamesAndSets.insert(QStringLiteral("QueueTest"), 2); + expectedNamesAndSets.insert(QStringLiteral("DummyTest"), 1); // used as parameterized test + expectedNamesAndSets.insert(QStringLiteral("DummyTest"), 1); // used as 'normal' test - QMap foundNamesAndSets = m_model->gtestNamesAndSets(); + QMultiMap foundNamesAndSets = m_model->gtestNamesAndSets(); QCOMPARE(expectedNamesAndSets.size(), foundNamesAndSets.size()); foreach (const QString &name, expectedNamesAndSets.keys()) - QCOMPARE(expectedNamesAndSets.value(name), foundNamesAndSets.value(name)); + QCOMPARE(expectedNamesAndSets.values(name), foundNamesAndSets.values(name)); // check also that no Qt related tests have been found QCOMPARE(m_model->autoTestsCount(), 0); diff --git a/plugins/autotest/autotestunittests.qrc b/plugins/autotest/autotestunittests.qrc index 96e5b05a31a..861f5c26654 100644 --- a/plugins/autotest/autotestunittests.qrc +++ b/plugins/autotest/autotestunittests.qrc @@ -50,5 +50,8 @@ unit_test/simple_gt/tests/tests.pro unit_test/simple_gt/simple_gt.pro unit_test/simple_gt/tests/gtest_dependency.pri + unit_test/simple_gt/tests/gt3/dummytest.h + unit_test/simple_gt/tests/gt3/gt3.pro + unit_test/simple_gt/tests/gt3/main.cpp diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index b52a768ef2b..d6e4d1d724d 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -824,9 +824,9 @@ int TestTreeModel::gtestNamesCount() const return m_googleTestRootItem ? m_googleTestRootItem->childCount() : 0; } -QMap TestTreeModel::gtestNamesAndSets() const +QMultiMap TestTreeModel::gtestNamesAndSets() const { - QMap result; + QMultiMap result; if (m_googleTestRootItem) { for (int row = 0, count = m_googleTestRootItem->childCount(); row < count; ++row) { diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 2f7f00a4e87..c8eefd042fc 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -70,7 +70,7 @@ public: int unnamedQuickTestsCount() const; int dataTagsCount() const; int gtestNamesCount() const; - QMap gtestNamesAndSets() const; + QMultiMap gtestNamesAndSets() const; #endif signals: diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt3/dummytest.h b/plugins/autotest/unit_test/simple_gt/tests/gt3/dummytest.h new file mode 100644 index 00000000000..b8fac8e799d --- /dev/null +++ b/plugins/autotest/unit_test/simple_gt/tests/gt3/dummytest.h @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ +#include + +#include + +class DummyTest : public ::testing::TestWithParam +{ +protected: + virtual void SetUp() { + m_str1 = QString::fromLatin1(GetParam()).toLower(); + + m_str2 = QString::fromLatin1(GetParam()).toUpper(); + + m_str3 = QString::fromLatin1(GetParam()).toHtmlEscaped(); + } + + QString m_str1; + QString m_str2; + QString m_str3; +}; diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt3/gt3.pro b/plugins/autotest/unit_test/simple_gt/tests/gt3/gt3.pro new file mode 100644 index 00000000000..4830351f08f --- /dev/null +++ b/plugins/autotest/unit_test/simple_gt/tests/gt3/gt3.pro @@ -0,0 +1,12 @@ +include(../gtest_dependency.pri) + +TEMPLATE = app +CONFIG += qt console c++11 +CONFIG -= app_bundle + +HEADERS += \ + dummytest.h + +SOURCES += \ + main.cpp + diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp b/plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp new file mode 100644 index 00000000000..088506ec555 --- /dev/null +++ b/plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at +** http://www.qt.io/contact-us +** +** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ +#include +#include + +#include "dummytest.h" + +using namespace testing; + +#include +#include + +static QMap testValues = { + { "DummyTest", + {QStringLiteral("dummytest"), QStringLiteral("DUMMYTEST"), QStringLiteral("DummyTest")} + }, + { "Hello World", + {QStringLiteral("hello world"), QStringLiteral("HELLO WORLD"), QStringLiteral("Hello World")} + }, + { "#include \n#include \"test.h\"", + {QStringLiteral("#include \n#include \"test.h\""), + QStringLiteral("#INCLUDE \n#INCLUDE \"TEST.H\""), + QStringLiteral("#include <QString>\n#include "test.h"") + } + } +}; + +static QMap testValuesSec = { + { "BlAh", + {QStringLiteral("blah"), QStringLiteral("BLAH"), QStringLiteral("BlAh")} + }, + { "", + {QStringLiteral(""), QStringLiteral(""), QStringLiteral("<html>")} + }, +}; + +INSTANTIATE_TEST_CASE_P(First, DummyTest, ::testing::ValuesIn(testValues.keys())); +INSTANTIATE_TEST_CASE_P(Second, DummyTest, ::testing::ValuesIn(testValuesSec.keys())); + +TEST_P(DummyTest, Easy) +{ + // total wrong usage, but this is for testing purpose + bool first = testValues.contains(GetParam()); + bool second = testValuesSec.contains(GetParam()); + QStringList expected; + if (first) + expected = testValues.value(GetParam()); + else if (second) + expected = testValuesSec.value(GetParam()); + else + FAIL(); + + ASSERT_EQ(3, expected.size()); + + EXPECT_EQ(m_str1, expected.at(0)); + EXPECT_EQ(m_str2, expected.at(1)); + EXPECT_EQ(m_str3, expected.at(2)); +} + +TEST(DummyTest, BlaBlubb) +{ + ASSERT_EQ(3, testValues.size()); +} + +int main(int argc, char *argv[]) +{ + InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/plugins/autotest/unit_test/simple_gt/tests/tests.pro b/plugins/autotest/unit_test/simple_gt/tests/tests.pro index 77f3621946d..424362adbdf 100644 --- a/plugins/autotest/unit_test/simple_gt/tests/tests.pro +++ b/plugins/autotest/unit_test/simple_gt/tests/tests.pro @@ -1,4 +1,5 @@ TEMPLATE = subdirs SUBDIRS += gt1 \ - gt2 + gt2 \ + gt3 From 00f93b95a721e2c8f0264981450e85a7a5a54bbf Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 13 Jan 2016 10:57:32 +0100 Subject: [PATCH 185/200] Make parameterized gtests visually distinguishable Change-Id: I08642a5988b43b3bbbb7209564561860219f4d1a Reviewed-by: Niels Weber --- plugins/autotest/testtreeitem.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index 59318bda5e8..e514e9cd704 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -93,6 +93,8 @@ QVariant TestTreeItem::data(int /*column*/, int role) const return QString(m_name + QObject::tr(" (none)")); else if (m_name.isEmpty()) return QObject::tr(Constants::UNNAMED_QUICKTESTS); + else if (m_type == GTestCaseParameterized) + return QString(m_name + QObject::tr(" [parameterized]")); else return m_name; case Qt::ToolTipRole: From eca35ce8684b833ae8d878fdb21faf7fd4cea1bb Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 15 Jan 2016 07:21:38 +0100 Subject: [PATCH 186/200] Make disabled a state instead of separate type State will be enhanced later on to provide better support for gtest. Change-Id: I3f3f6b986d6a25ebd36fe44330c792608844b35c Reviewed-by: Niels Weber --- plugins/autotest/testcodeparser.cpp | 5 ++++- plugins/autotest/testtreeitem.cpp | 18 +++++++++++------- plugins/autotest/testtreeitem.h | 22 ++++++++++++++++++---- plugins/autotest/testtreeitemdelegate.cpp | 2 +- plugins/autotest/testtreemodel.cpp | 2 -- plugins/autotest/testvisitor.cpp | 7 +++++-- 6 files changed, 39 insertions(+), 17 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 0b73568443f..9270a6d4548 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -434,6 +434,7 @@ static TestTreeItem *constructTestTreeItem(const QString &fileName, locationAndType.m_type); treeItemChild->setLine(locationAndType.m_line); treeItemChild->setColumn(locationAndType.m_column); + treeItemChild->setState(locationAndType.m_state); // check for data tags and if there are any for this function add them const QString qualifiedFunctionName = testCaseName + QLatin1String("::") + functionName; @@ -445,6 +446,7 @@ static TestTreeItem *constructTestTreeItem(const QString &fileName, tagLocation.m_type); tagTreeItem->setLine(tagLocation.m_line); tagTreeItem->setColumn(tagLocation.m_column); + tagTreeItem->setState(tagLocation.m_state); treeItemChild->appendChild(tagTreeItem); } } @@ -464,6 +466,7 @@ static TestTreeItem *constructGTestTreeItem(const QString &filePath, const GTest foreach (const TestCodeLocationAndType &locationAndType, testSets) { TestTreeItem *treeItemChild = new TestTreeItem(locationAndType.m_name, filePath, locationAndType.m_type); + treeItemChild->setState(locationAndType.m_state); treeItemChild->setLine(locationAndType.m_line); treeItemChild->setColumn(locationAndType.m_column); treeItemChild->setMainFile(proFile); @@ -1032,7 +1035,7 @@ void TestCodeParser::updateGTests(const CPlusPlus::Document::Ptr &doc, info.setProFile(proFile); foreach (const TestCodeLocationAndType &testSet, tests.value(testSpec)) { GTestInfo gtestInfo(testSpec.testCaseName, testSet.m_name, fileName); - if (testSet.m_type == TestTreeItem::GTestNameDisabled) + if (testSet.m_state & TestTreeItem::Disabled) gtestInfo.setEnabled(false); m_gtestDocList.append(gtestInfo); } diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index e514e9cd704..e6ea3a89131 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -34,7 +34,8 @@ TestTreeItem::TestTreeItem(const QString &name, const QString &filePath, Type ty m_name(name), m_filePath(filePath), m_type(type), - m_line(0) + m_line(0), + m_state(Enabled) { switch (m_type) { case TestClass: @@ -42,7 +43,6 @@ TestTreeItem::TestTreeItem(const QString &name, const QString &filePath, Type ty case GTestCase: case GTestCaseParameterized: case GTestName: - case GTestNameDisabled: m_checked = Qt::Checked; break; default: @@ -63,7 +63,8 @@ TestTreeItem::TestTreeItem(const TestTreeItem &other) m_type(other.m_type), m_line(other.m_line), m_column(other.m_column), - m_mainFile(other.m_mainFile) + m_mainFile(other.m_mainFile), + m_state(other.m_state) { for (int row = 0, count = other.childCount(); row < count; ++row) appendChild(new TestTreeItem(*childItem(row))); @@ -118,7 +119,6 @@ QVariant TestTreeItem::data(int /*column*/, int role) const return m_name.isEmpty() ? QVariant() : checked(); case TestFunction: case GTestName: - case GTestNameDisabled: if (parentItem() && parentItem()->name().isEmpty()) return QVariant(); return checked(); @@ -144,6 +144,8 @@ QVariant TestTreeItem::data(int /*column*/, int role) const } case TypeRole: return m_type; + case StateRole: + return (int)m_state; } return QVariant(); } @@ -181,6 +183,10 @@ bool TestTreeItem::modifyContent(const TestTreeItem *modified) m_type = modified->m_type; hasBeenModified = true; } + if (m_state != modified->m_state) { + m_state = modified->m_state; + hasBeenModified = true; + } return hasBeenModified; } @@ -188,8 +194,7 @@ void TestTreeItem::setChecked(const Qt::CheckState checkState) { switch (m_type) { case TestFunction: - case GTestName: - case GTestNameDisabled: { + case GTestName: { m_checked = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked); parentItem()->revalidateCheckState(); break; @@ -215,7 +220,6 @@ Qt::CheckState TestTreeItem::checked() const case GTestCase: case GTestCaseParameterized: case GTestName: - case GTestNameDisabled: return m_checked; case TestDataFunction: case TestSpecialFunction: diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index ac4134ee36a..bc6038809c8 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -30,7 +30,8 @@ namespace { enum ItemRole { LinkRole = Qt::UserRole + 2, // can be removed if AnnotationRole comes back ItalicRole, // used only inside the delegate - TypeRole + TypeRole, + StateRole }; } @@ -41,7 +42,8 @@ class TestTreeItem : public Utils::TreeItem { public: - enum Type { + enum Type + { Root, TestClass, TestFunction, @@ -50,10 +52,18 @@ public: TestSpecialFunction, GTestCase, GTestCaseParameterized, - GTestName, - GTestNameDisabled + GTestName }; + enum TestState + { + Enabled = 0x00, + Disabled = 0x01, + }; + + Q_FLAGS(TestState) + Q_DECLARE_FLAGS(TestStates, TestState) + TestTreeItem(const QString &name = QString(), const QString &filePath = QString(), Type type = Root); virtual ~TestTreeItem(); @@ -74,6 +84,8 @@ public: void setChecked(const Qt::CheckState checked); Qt::CheckState checked() const; Type type() const { return m_type; } + void setState(TestStates states) { m_state = states; } + TestStates state() const { return m_state; } QList getChildNames() const; TestTreeItem *parentItem() const; TestTreeItem *childItem(int row) const; @@ -88,6 +100,7 @@ private: unsigned m_line; unsigned m_column; QString m_mainFile; // main for Quick tests, project file for gtest + TestStates m_state; }; struct TestCodeLocationAndType { @@ -95,6 +108,7 @@ struct TestCodeLocationAndType { unsigned m_line; unsigned m_column; TestTreeItem::Type m_type; + TestTreeItem::TestStates m_state; }; typedef QVector TestCodeLocationList; diff --git a/plugins/autotest/testtreeitemdelegate.cpp b/plugins/autotest/testtreeitemdelegate.cpp index 17475e2326a..e17e6029c97 100644 --- a/plugins/autotest/testtreeitemdelegate.cpp +++ b/plugins/autotest/testtreeitemdelegate.cpp @@ -65,7 +65,7 @@ void TestTreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem & } // paint disabled googletests in gray - if (index.data(TypeRole).toInt() == TestTreeItem::GTestNameDisabled) + if (index.data(StateRole).toInt() & TestTreeItem::Disabled) opt.palette.setColor(QPalette::Text, QColor(0xa0, 0xa0, 0xa0)); QStyledItemDelegate::paint(painter, opt, index); diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index d6e4d1d724d..19f47e40006 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -146,7 +146,6 @@ bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int break; case TestTreeItem::TestFunction: case TestTreeItem::GTestName: - case TestTreeItem::GTestNameDisabled: emit dataChanged(index.parent(), index.parent()); break; default: // avoid warning regarding unhandled enum member @@ -173,7 +172,6 @@ Qt::ItemFlags TestTreeModel::flags(const QModelIndex &index) const return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsTristate | Qt::ItemIsUserCheckable; case TestTreeItem::TestFunction: case TestTreeItem::GTestName: - case TestTreeItem::GTestNameDisabled: if (item->parentItem()->name().isEmpty()) return Qt::ItemIsEnabled | Qt::ItemIsSelectable; return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable; diff --git a/plugins/autotest/testvisitor.cpp b/plugins/autotest/testvisitor.cpp index 9c4d4d272d8..256e679d2fc 100644 --- a/plugins/autotest/testvisitor.cpp +++ b/plugins/autotest/testvisitor.cpp @@ -89,6 +89,7 @@ bool TestVisitor::visit(CPlusPlus::Class *symbol) locationAndType.m_type = TestTreeItem::TestDataFunction; else locationAndType.m_type = TestTreeItem::TestFunction; + locationAndType.m_state = TestTreeItem::Enabled; m_privSlots.insert(name, locationAndType); } } @@ -218,6 +219,7 @@ bool TestDataFunctionVisitor::visit(CPlusPlus::CallAST *ast) locationAndType.m_column = column - 1; locationAndType.m_line = line; locationAndType.m_type = TestTreeItem::TestDataTag; + locationAndType.m_state = TestTreeItem::Enabled; m_currentTags.append(locationAndType); } } @@ -329,6 +331,7 @@ bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast) else locationAndType.m_type = TestTreeItem::TestFunction; + locationAndType.m_state = TestTreeItem::Enabled; m_testFunctions.insert(name.toString(), locationAndType); } return false; @@ -378,8 +381,8 @@ bool GTestVisitor::visit(CPlusPlus::FunctionDefinitionAST *ast) locationAndType.m_name = disabled ? testName.mid(9) : testName; locationAndType.m_line = line; locationAndType.m_column = column - 1; - locationAndType.m_type = disabled ? TestTreeItem::GTestNameDisabled - : TestTreeItem::GTestName; + locationAndType.m_type = TestTreeItem::GTestName; + locationAndType.m_state = disabled ? TestTreeItem::Disabled : TestTreeItem::Enabled; GTestCaseSpec spec; spec.testCaseName = testCaseName; spec.parameterized = TestUtils::isGTestParameterized(prettyName); From d0b258a5dfba374b557d176307e9665a447df891 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 18 Jan 2016 14:37:32 +0100 Subject: [PATCH 187/200] Make TestRunner more thread-safe Change-Id: I42e5c9e26a45ef2875cf70e1c5e3b989bcce4de8 Reviewed-by: Eike Ziller --- plugins/autotest/testconfiguration.h | 10 ++++------ plugins/autotest/testrunner.cpp | 17 +++++++++-------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/plugins/autotest/testconfiguration.h b/plugins/autotest/testconfiguration.h index 7b39ae879cb..7fb915fbb55 100644 --- a/plugins/autotest/testconfiguration.h +++ b/plugins/autotest/testconfiguration.h @@ -22,15 +22,13 @@ #include "autotestconstants.h" +#include #include #include +#include #include -namespace ProjectExplorer { -class Project; -} - namespace Autotest { namespace Internal { @@ -68,7 +66,7 @@ public: QString workingDirectory() const { return m_workingDir; } QString displayName() const { return m_displayName; } Utils::Environment environment() const { return m_environment; } - ProjectExplorer::Project *project() const { return m_project; } + ProjectExplorer::Project *project() const { return m_project.data(); } bool unnamedOnly() const { return m_unnamedOnly; } bool guessedConfiguration() const { return m_guessedConfiguration; } TestType testType() const { return m_type; } @@ -85,7 +83,7 @@ private: QString m_workingDir; QString m_displayName; Utils::Environment m_environment; - ProjectExplorer::Project *m_project; + QPointer m_project; bool m_guessedConfiguration; TestType m_type; }; diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 84d500ccdcf..67f9ead4f6a 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -44,7 +44,7 @@ namespace Internal { static TestRunner *m_instance = 0; -void emitTestResultCreated(TestResult *testResult) +static void emitTestResultCreated(TestResult *testResult) { emit m_instance->testResultCreated(testResult); } @@ -105,9 +105,9 @@ void TestRunner::setSelectedTests(const QList &selected) m_selectedTests = selected; } -void performTestRun(QFutureInterface &futureInterface, - const QList selectedTests, const int timeout, - const QString metricsOption, TestRunner* testRunner) +static void performTestRun(QFutureInterface &futureInterface, + const QList selectedTests, const int timeout, + const QString metricsOption) { int testCaseCount = 0; foreach (TestConfiguration *config, selectedTests) { @@ -124,9 +124,6 @@ void performTestRun(QFutureInterface &futureInterface, QProcess testProcess; testProcess.setReadChannelMode(QProcess::MergedChannels); testProcess.setReadChannel(QProcess::StandardOutput); - QObject::connect(testRunner, &TestRunner::requestStopTestRun, &testProcess, [&] () { - futureInterface.cancel(); // this kills the process if that is still in the running loop - }); TestOutputReader outputReader(&testProcess); QObject::connect(&outputReader, &TestOutputReader::increaseProgress, [&] () { @@ -278,11 +275,15 @@ void TestRunner::runTests() Qt::QueuedConnection); QFuture future = QtConcurrent::run(&performTestRun, m_selectedTests, settings->timeout, - metricsOption, this); + metricsOption); + Core::FutureProgress *progress = Core::ProgressManager::addTask(future, tr("Running Tests"), Autotest::Constants::TASK_INDEX); connect(progress, &Core::FutureProgress::finished, TestRunner::instance(), &TestRunner::onFinished); + connect(this, &TestRunner::requestStopTestRun, progress, [progress]() { + progress->future().cancel(); + }); } void TestRunner::buildProject(ProjectExplorer::Project *project) From 9a3efd49503afd728dd45a8cb4610036fb1c4ebe Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 19 Jan 2016 11:58:47 +0100 Subject: [PATCH 188/200] Don't show focus frame on OS X The focus frame needs a border around the view, but there isn't. Change-Id: I9d7b206445be9f8e43bd9168ccea2075f4ac4bb7 Reviewed-by: Christian Stenger --- plugins/autotest/testresultspane.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 42886027fc2..df84ebd1b20 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -54,7 +54,9 @@ namespace Internal { ResultsTreeView::ResultsTreeView(QWidget *parent) : Utils::TreeView(parent) -{} +{ + setAttribute(Qt::WA_MacShowFocusRect, false); +} void ResultsTreeView::keyPressEvent(QKeyEvent *event) { From 06e02480f4d72f588b165fa32263c37fa508b5ba Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 19 Jan 2016 12:02:07 +0100 Subject: [PATCH 189/200] Use Utils::runAsync instead of QtConcurrent::run QtConcurrent has the issue that it uses a globally shared thread pool, with no finer granularity for simulataneous tasks. Create an explicit event loop for the test runner for that. Change-Id: Idcf2f125e111d94a5a60e5b136fd875225326e14 Reviewed-by: Christian Stenger --- plugins/autotest/testcodeparser.cpp | 2 +- plugins/autotest/testrunner.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 9270a6d4548..556fc735e2a 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -800,7 +800,7 @@ void TestCodeParser::scanForTests(const QStringList &fileList) return; } - QFuture future = QtConcurrent::run(&performParse, list, this); + QFuture future = Utils::runAsync(&performParse, list, this); Core::FutureProgress *progress = Core::ProgressManager::addTask(future, isFullParse ? tr("Scanning for Tests") : tr("Refreshing Tests List"), diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 67f9ead4f6a..cde0dde4bfb 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -109,6 +109,7 @@ static void performTestRun(QFutureInterface &futureInterface, const QList selectedTests, const int timeout, const QString metricsOption) { + QEventLoop eventLoop; int testCaseCount = 0; foreach (TestConfiguration *config, selectedTests) { config->completeTestInformation(); @@ -198,7 +199,7 @@ static void performTestRun(QFutureInterface &futureInterface, emitTestResultCreated(new FaultyTestResult(Result::MessageFatal, QObject::tr("Test run canceled by user."))); } - qApp->processEvents(); + eventLoop.processEvents(); } } @@ -274,8 +275,8 @@ void TestRunner::runTests() TestResultsPane::instance(), &TestResultsPane::addTestResult, Qt::QueuedConnection); - QFuture future = QtConcurrent::run(&performTestRun, m_selectedTests, settings->timeout, - metricsOption); + QFuture future = Utils::runAsync(&performTestRun, m_selectedTests, settings->timeout, + metricsOption); Core::FutureProgress *progress = Core::ProgressManager::addTask(future, tr("Running Tests"), Autotest::Constants::TASK_INDEX); From dc4e955126af880788ebf545ba1df9f66e745195 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 15 Jan 2016 12:24:10 +0100 Subject: [PATCH 190/200] Fix construction of source file for test results Change-Id: I9dff118aa8f8871812e1881f0c73220d56ab16d5 Reviewed-by: Niels Weber --- plugins/autotest/testoutputreader.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/autotest/testoutputreader.cpp b/plugins/autotest/testoutputreader.cpp index df4083b3083..4ebfed8e7c0 100644 --- a/plugins/autotest/testoutputreader.cpp +++ b/plugins/autotest/testoutputreader.cpp @@ -210,9 +210,11 @@ void TestOutputReader::processOutput() result = TestResult::resultFromString( attributes.value(QStringLiteral("type")).toString()); file = decode(attributes.value(QStringLiteral("file")).toString()); - if (!file.isEmpty()) - file = constructSourceFilePath(m_testApplication->workingDirectory(), file, + if (!file.isEmpty()) { + const QString base = QFileInfo(m_testApplication->program()).absolutePath(); + file = constructSourceFilePath(base, file, m_testApplication->program()); + } lineNumber = attributes.value(QStringLiteral("line")).toInt(); } else if (currentTag == QStringLiteral("BenchmarkResult")) { const QXmlStreamAttributes &attributes = xmlReader.attributes(); @@ -400,8 +402,8 @@ void TestOutputReader::processGTestOutput() int firstColon = description.indexOf(QLatin1Char(':')); if (firstColon != -1) { int secondColon = description.indexOf(QLatin1Char(':'), firstColon + 1); - QString file = constructSourceFilePath(m_testApplication->workingDirectory(), - description.left(firstColon), + const QString base = QFileInfo(m_testApplication->program()).absolutePath(); + QString file = constructSourceFilePath(base, description.left(firstColon), m_testApplication->program()); QString line = description.mid(firstColon + 1, secondColon - firstColon - 1); testResult->setFileName(file); From ca8f7c56cdad3d6add748dd2cd0311e02942c87b Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 18 Jan 2016 07:14:48 +0100 Subject: [PATCH 191/200] Remove bold tag from test summary In some themes this becomes hard to read. Change-Id: If703355c1b76f3120f29c1e3ca1363f502d23865 Reviewed-by: Niels Weber --- plugins/autotest/testresultspane.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index df84ebd1b20..3e2863a7417 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -426,7 +426,7 @@ void TestResultsPane::initializeFilterMenu() void TestResultsPane::updateSummaryLabel() { - QString labelText = QString::fromLatin1("

Test summary:   %1 %2, %3 %4") + QString labelText = QString::fromLatin1("

Test summary:   %1 %2, %3 %4") .arg(QString::number(m_model->resultTypeCount(Result::Pass)), tr("passes"), QString::number(m_model->resultTypeCount(Result::Fail)), tr("fails")); int count = m_model->resultTypeCount(Result::UnexpectedPass); From 3b423602eddd36380a98b2e2388ceabdd80a3db1 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 19 Jan 2016 14:24:09 +0100 Subject: [PATCH 192/200] Report test results through QFutureInterface Change-Id: Id5704ff2744ee925978c518f44069b26c66d682e Reviewed-by: Christian Stenger --- plugins/autotest/testoutputreader.cpp | 45 ++++++++------- plugins/autotest/testoutputreader.h | 18 ++---- plugins/autotest/testresultspane.cpp | 2 + plugins/autotest/testrunner.cpp | 83 ++++++++++----------------- plugins/autotest/testrunner.h | 4 +- 5 files changed, 64 insertions(+), 88 deletions(-) diff --git a/plugins/autotest/testoutputreader.cpp b/plugins/autotest/testoutputreader.cpp index 4ebfed8e7c0..319f8d7ee3e 100644 --- a/plugins/autotest/testoutputreader.cpp +++ b/plugins/autotest/testoutputreader.cpp @@ -131,10 +131,15 @@ static QString constructBenchmarkInformation(const QString &metric, double value .arg(iterations); } -TestOutputReader::TestOutputReader(QProcess *testApplication, OutputType type) - : m_testApplication(testApplication) - , m_type(type) +TestOutputReader::TestOutputReader(QFutureInterface futureInterface, + QProcess *testApplication, TestType type) + : m_testApplication(testApplication), + m_futureInterface(futureInterface) { + if (type == TestTypeQt) + connect(testApplication, &QProcess::readyRead, this, &TestOutputReader::processOutput); + else + connect(testApplication, &QProcess::readyRead, this, &TestOutputReader::processGTestOutput); } enum CDATAMode { @@ -186,7 +191,7 @@ void TestOutputReader::processOutput() auto testResult = new QTestResult(className); testResult->setResult(Result::MessageTestCaseStart); testResult->setDescription(tr("Executing test case %1").arg(className)); - testResultCreated(testResult); + m_futureInterface.reportResult(testResult); } else if (currentTag == QStringLiteral("TestFunction")) { testCase = xmlReader.attributes().value(QStringLiteral("name")).toString(); QTC_ASSERT(!testCase.isEmpty(), continue); @@ -194,7 +199,7 @@ void TestOutputReader::processOutput() testResult->setResult(Result::MessageCurrentTest); testResult->setDescription(tr("Entering test function %1::%2").arg(className, testCase)); - testResultCreated(testResult); + m_futureInterface.reportResult(testResult); } else if (currentTag == QStringLiteral("Duration")) { duration = xmlReader.attributes().value(QStringLiteral("msecs")).toString(); QTC_ASSERT(!duration.isEmpty(), continue); @@ -280,16 +285,16 @@ void TestOutputReader::processOutput() testResult->setTestCase(testCase); testResult->setResult(Result::MessageInternal); testResult->setDescription(tr("Execution took %1 ms.").arg(duration)); - testResultCreated(testResult); + m_futureInterface.reportResult(testResult); } - emit increaseProgress(); + m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1); } else if (currentTag == QStringLiteral("TestCase")) { auto testResult = new QTestResult(className); testResult->setResult(Result::MessageTestCaseEnd); testResult->setDescription( duration.isEmpty() ? tr("Test finished.") : tr("Test execution took %1 ms.").arg(duration)); - testResultCreated(testResult); + m_futureInterface.reportResult(testResult); } else if (validEndTags.contains(currentTag.toString())) { auto testResult = new QTestResult(className); testResult->setTestCase(testCase); @@ -298,7 +303,7 @@ void TestOutputReader::processOutput() testResult->setFileName(file); testResult->setLine(lineNumber); testResult->setDescription(description); - testResultCreated(testResult); + m_futureInterface.reportResult(testResult); } break; } @@ -348,7 +353,7 @@ void TestOutputReader::processGTestOutput() auto testResult = new GTestResult(); testResult->setResult(Result::MessageInternal); testResult->setDescription(line); - testResultCreated(testResult); + m_futureInterface.reportResult(testResult); description.clear(); } else if (disabledTests.exactMatch(line)) { auto testResult = new GTestResult(); @@ -356,7 +361,7 @@ void TestOutputReader::processGTestOutput() int disabled = disabledTests.cap(1).toInt(); testResult->setDescription(tr("You have %n disabled test(s).", 0, disabled)); testResult->setLine(disabled); // misuse line property to hold number of disabled - testResultCreated(testResult); + m_futureInterface.reportResult(testResult); description.clear(); } continue; @@ -367,7 +372,7 @@ void TestOutputReader::processGTestOutput() testResult->setTestCase(currentTestSet); testResult->setResult(Result::MessageTestCaseEnd); testResult->setDescription(tr("Test execution took %1").arg(testEnds.cap(2))); - testResultCreated(testResult); + m_futureInterface.reportResult(testResult); currentTestName.clear(); currentTestSet.clear(); } else if (newTestStarts.exactMatch(line)) { @@ -375,24 +380,24 @@ void TestOutputReader::processGTestOutput() auto testResult = new GTestResult(currentTestName); testResult->setResult(Result::MessageTestCaseStart); testResult->setDescription(tr("Executing test case %1").arg(currentTestName)); - testResultCreated(testResult); + m_futureInterface.reportResult(testResult); } else if (newTestSetStarts.exactMatch(line)) { currentTestSet = newTestSetStarts.cap(1); auto testResult = new GTestResult(); testResult->setResult(Result::MessageCurrentTest); testResult->setDescription(tr("Entering test set %1").arg(currentTestSet)); - testResultCreated(testResult); + m_futureInterface.reportResult(testResult); } else if (testSetSuccess.exactMatch(line)) { auto testResult = new GTestResult(currentTestName); testResult->setTestCase(currentTestSet); testResult->setResult(Result::Pass); - testResultCreated(testResult); + m_futureInterface.reportResult(testResult); testResult = new GTestResult(currentTestName); testResult->setTestCase(currentTestSet); testResult->setResult(Result::MessageInternal); testResult->setDescription(tr("Execution took %1.").arg(testSetSuccess.cap(2))); - testResultCreated(testResult); - emit increaseProgress(); + m_futureInterface.reportResult(testResult); + m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1); } else if (testSetFail.exactMatch(line)) { auto testResult = new GTestResult(currentTestName); testResult->setTestCase(currentTestSet); @@ -409,14 +414,14 @@ void TestOutputReader::processGTestOutput() testResult->setFileName(file); testResult->setLine(line.toInt()); } - testResultCreated(testResult); + m_futureInterface.reportResult(testResult); description.clear(); testResult = new GTestResult(currentTestName); testResult->setTestCase(currentTestSet); testResult->setResult(Result::MessageInternal); testResult->setDescription(tr("Execution took %1.").arg(testSetFail.cap(2))); - testResultCreated(testResult); - emit increaseProgress(); + m_futureInterface.reportResult(testResult); + m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1); } } } diff --git a/plugins/autotest/testoutputreader.h b/plugins/autotest/testoutputreader.h index 532e081a03f..8c9fd789b60 100644 --- a/plugins/autotest/testoutputreader.h +++ b/plugins/autotest/testoutputreader.h @@ -22,6 +22,7 @@ #include "testresult.h" +#include #include #include @@ -36,24 +37,15 @@ class TestOutputReader : public QObject { Q_OBJECT public: - enum OutputType { - Qt, - GTest - }; + TestOutputReader(QFutureInterface futureInterface, + QProcess *testApplication, TestType type); - TestOutputReader(QProcess *testApplication, OutputType type = Qt); - -public slots: +private: void processOutput(); void processGTestOutput(); -signals: - void testResultCreated(TestResult *testResult); - void increaseProgress(); - -private: QProcess *m_testApplication; // not owned - OutputType m_type; + QFutureInterface m_futureInterface; }; } // namespace Internal diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 3e2863a7417..0114279c555 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -128,6 +128,8 @@ TestResultsPane::TestResultsPane(QObject *parent) : this, &TestResultsPane::onTestRunStarted); connect(TestRunner::instance(), &TestRunner::testRunFinished, this, &TestResultsPane::onTestRunFinished); + connect(TestRunner::instance(), &TestRunner::testResultReady, + this, &TestResultsPane::addTestResult); } void TestResultsPane::createToolButtons() diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index cde0dde4bfb..e23d4b58b26 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -36,7 +36,6 @@ #include #include -#include #include namespace Autotest { @@ -44,11 +43,6 @@ namespace Internal { static TestRunner *m_instance = 0; -static void emitTestResultCreated(TestResult *testResult) -{ - emit m_instance->testResultCreated(testResult); -} - static QString executableFilePath(const QString &command, const QProcessEnvironment &environment) { if (command.isEmpty()) @@ -89,6 +83,17 @@ TestRunner::TestRunner(QObject *parent) : QObject(parent), m_executingTests(false) { + connect(&m_futureWatcher, &QFutureWatcher::resultReadyAt, + this, [this](int index) { emit testResultReady(m_futureWatcher.resultAt(index)); }); + connect(&m_futureWatcher, &QFutureWatcher::finished, + this, &TestRunner::onFinished); + connect(this, &TestRunner::requestStopTestRun, + &m_futureWatcher, &QFutureWatcher::cancel); + connect(&m_futureWatcher, &QFutureWatcher::canceled, + this, [this]() { emit testResultReady(new FaultyTestResult( + Result::MessageFatal, + QObject::tr("Test run canceled by user."))); + }); } TestRunner::~TestRunner() @@ -105,7 +110,7 @@ void TestRunner::setSelectedTests(const QList &selected) m_selectedTests = selected; } -static void performTestRun(QFutureInterface &futureInterface, +static void performTestRun(QFutureInterface &futureInterface, const QList selectedTests, const int timeout, const QString metricsOption) { @@ -116,7 +121,7 @@ static void performTestRun(QFutureInterface &futureInterface, if (config->project()) { testCaseCount += config->testCaseCount(); } else { - emitTestResultCreated(new FaultyTestResult(Result::MessageWarn, + futureInterface.reportResult(new FaultyTestResult(Result::MessageWarn, QObject::tr("Project is null for \"%1\". Removing from test run.\n" "Check the test environment.").arg(config->displayName()))); } @@ -126,28 +131,12 @@ static void performTestRun(QFutureInterface &futureInterface, testProcess.setReadChannelMode(QProcess::MergedChannels); testProcess.setReadChannel(QProcess::StandardOutput); - TestOutputReader outputReader(&testProcess); - QObject::connect(&outputReader, &TestOutputReader::increaseProgress, [&] () { - futureInterface.setProgressValue(futureInterface.progressValue() + 1); - }); - QObject::connect(&outputReader, &TestOutputReader::testResultCreated, &emitTestResultCreated); - futureInterface.setProgressRange(0, testCaseCount); futureInterface.setProgressValue(0); - QMetaObject::Connection connection; foreach (const TestConfiguration *testConfiguration, selectedTests) { - if (connection) - QObject::disconnect(connection); - - TestType testType = testConfiguration->testType(); - if (testType == TestTypeQt) { - connection = QObject::connect(&testProcess, &QProcess::readyRead, &outputReader, - &TestOutputReader::processOutput); - } else { - connection = QObject::connect(&testProcess, &QProcess::readyRead, &outputReader, - &TestOutputReader::processGTestOutput); - } + TestOutputReader outputReader(futureInterface, &testProcess, testConfiguration->testType()); + Q_UNUSED(outputReader); if (futureInterface.isCanceled()) break; @@ -157,14 +146,14 @@ static void performTestRun(QFutureInterface &futureInterface, QProcessEnvironment environment = testConfiguration->environment().toProcessEnvironment(); QString commandFilePath = executableFilePath(testConfiguration->targetFile(), environment); if (commandFilePath.isEmpty()) { - emitTestResultCreated(new FaultyTestResult(Result::MessageFatal, + futureInterface.reportResult(new FaultyTestResult(Result::MessageFatal, QObject::tr("Could not find command \"%1\". (%2)") .arg(testConfiguration->targetFile()) .arg(testConfiguration->displayName()))); continue; } - if (testType == TestTypeQt) { + if (testConfiguration->testType() == TestTypeQt) { QStringList argumentList(QLatin1String("-xml")); if (!metricsOption.isEmpty()) argumentList << metricsOption; @@ -196,8 +185,7 @@ static void performTestRun(QFutureInterface &futureInterface, if (futureInterface.isCanceled()) { testProcess.kill(); testProcess.waitForFinished(); - emitTestResultCreated(new FaultyTestResult(Result::MessageFatal, - QObject::tr("Test run canceled by user."))); + return; } eventLoop.processEvents(); } @@ -207,7 +195,7 @@ static void performTestRun(QFutureInterface &futureInterface, if (testProcess.state() != QProcess::NotRunning) { testProcess.kill(); testProcess.waitForFinished(); - emitTestResultCreated(new FaultyTestResult(Result::MessageFatal, QObject::tr( + futureInterface.reportResult(new FaultyTestResult(Result::MessageFatal, QObject::tr( "Test case canceled due to timeout. \nMaybe raise the timeout?"))); } } @@ -227,14 +215,14 @@ void TestRunner::prepareToRunTests() foreach (TestConfiguration *config, m_selectedTests) { if (!omitRunConfigWarnings && config->guessedConfiguration()) { - TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MessageWarn, + emit testResultReady(new FaultyTestResult(Result::MessageWarn, tr("Project's run configuration was guessed for \"%1\".\n" "This might cause trouble during execution.").arg(config->displayName()))); } } if (m_selectedTests.empty()) { - TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MessageWarn, + emit testResultReady(new FaultyTestResult(Result::MessageWarn, tr("No tests selected. Canceling test run."))); onFinished(); return; @@ -242,7 +230,7 @@ void TestRunner::prepareToRunTests() ProjectExplorer::Project *project = m_selectedTests.at(0)->project(); if (!project) { - TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MessageWarn, + emit testResultReady(new FaultyTestResult(Result::MessageWarn, tr("Project is null. Canceling test run.\n" "Only desktop kits are supported. Make sure the " "currently active kit is a desktop kit."))); @@ -258,7 +246,7 @@ void TestRunner::prepareToRunTests() if (project->hasActiveBuildSettings()) { buildProject(project); } else { - TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MessageFatal, + emit testResultReady(new FaultyTestResult(Result::MessageFatal, tr("Project is not configured. Canceling test run."))); onFinished(); return; @@ -271,20 +259,10 @@ void TestRunner::runTests() const QSharedPointer settings = AutotestPlugin::instance()->settings(); const QString &metricsOption = TestSettings::metricsTypeToOption(settings->metrics); - connect(this, &TestRunner::testResultCreated, - TestResultsPane::instance(), &TestResultsPane::addTestResult, - Qt::QueuedConnection); - - QFuture future = Utils::runAsync(&performTestRun, m_selectedTests, settings->timeout, - metricsOption); - - Core::FutureProgress *progress = Core::ProgressManager::addTask(future, tr("Running Tests"), - Autotest::Constants::TASK_INDEX); - connect(progress, &Core::FutureProgress::finished, - TestRunner::instance(), &TestRunner::onFinished); - connect(this, &TestRunner::requestStopTestRun, progress, [progress]() { - progress->future().cancel(); - }); + QFuture future = Utils::runAsync(&performTestRun, m_selectedTests, + settings->timeout, metricsOption); + m_futureWatcher.setFuture(future); + Core::ProgressManager::addTask(future, tr("Running Tests"), Autotest::Constants::TASK_INDEX); } void TestRunner::buildProject(ProjectExplorer::Project *project) @@ -307,17 +285,14 @@ void TestRunner::buildFinished(bool success) if (success) { runTests(); } else { - TestResultsPane::instance()->addTestResult(new FaultyTestResult(Result::MessageFatal, - tr("Build failed. Canceling test run."))); + emit testResultReady(new FaultyTestResult(Result::MessageFatal, + tr("Build failed. Canceling test run."))); onFinished(); } } void TestRunner::onFinished() { - disconnect(this, &TestRunner::testResultCreated, - TestResultsPane::instance(), &TestResultsPane::addTestResult); - m_executingTests = false; emit testRunFinished(); } diff --git a/plugins/autotest/testrunner.h b/plugins/autotest/testrunner.h index e03a0c3d4d5..c3cd89ef60d 100644 --- a/plugins/autotest/testrunner.h +++ b/plugins/autotest/testrunner.h @@ -23,6 +23,7 @@ #include "testconfiguration.h" #include "testresult.h" +#include #include #include @@ -47,8 +48,8 @@ public: signals: void testRunStarted(); void testRunFinished(); - void testResultCreated(TestResult *testResult); void requestStopTestRun(); + void testResultReady(TestResult *result); public slots: void prepareToRunTests(); @@ -62,6 +63,7 @@ private: void runTests(); explicit TestRunner(QObject *parent = 0); + QFutureWatcher m_futureWatcher; QList m_selectedTests; bool m_executingTests; From e60a7a69237b96bf3808f4452adb8f4715cd5e7c Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 19 Jan 2016 13:31:55 +0100 Subject: [PATCH 193/200] Avoid possible race condition Change-Id: I12988ad9583740b2c72d8e40e68414a7cba08364 Reviewed-by: Niels Weber Reviewed-by: Eike Ziller --- plugins/autotest/testrunner.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index e23d4b58b26..d8b15c39a30 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -180,8 +180,13 @@ static void performTestRun(QFutureInterface &futureInterface, bool ok = testProcess.waitForStarted(); QTime executionTimer; executionTimer.start(); + bool canceledByTimeout = false; if (ok) { - while (testProcess.state() == QProcess::Running && executionTimer.elapsed() < timeout) { + while (testProcess.state() == QProcess::Running) { + if (executionTimer.elapsed() >= timeout) { + canceledByTimeout = true; + break; + } if (futureInterface.isCanceled()) { testProcess.kill(); testProcess.waitForFinished(); @@ -191,13 +196,13 @@ static void performTestRun(QFutureInterface &futureInterface, } } - if (executionTimer.elapsed() >= timeout) { + if (canceledByTimeout) { if (testProcess.state() != QProcess::NotRunning) { testProcess.kill(); testProcess.waitForFinished(); - futureInterface.reportResult(new FaultyTestResult(Result::MessageFatal, QObject::tr( - "Test case canceled due to timeout. \nMaybe raise the timeout?"))); } + futureInterface.reportResult(new FaultyTestResult(Result::MessageFatal, QObject::tr( + "Test case canceled due to timeout. \nMaybe raise the timeout?"))); } } futureInterface.setProgressValue(testCaseCount); From 166bf38a11bd4234ddca51abac0733ca4ae806f0 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 20 Jan 2016 08:26:10 +0100 Subject: [PATCH 194/200] Fix issue with manually canceling running tests... ...by restructuring TestOutputReader. Change-Id: Ia58b755a5b50afb66d53e9d254e450cce01621f4 Reviewed-by: Niels Weber --- plugins/autotest/testoutputreader.cpp | 246 ++++++++++++-------------- plugins/autotest/testoutputreader.h | 58 +++++- plugins/autotest/testrunner.cpp | 11 +- 3 files changed, 179 insertions(+), 136 deletions(-) diff --git a/plugins/autotest/testoutputreader.cpp b/plugins/autotest/testoutputreader.cpp index 319f8d7ee3e..609c139e123 100644 --- a/plugins/autotest/testoutputreader.cpp +++ b/plugins/autotest/testoutputreader.cpp @@ -28,7 +28,6 @@ #include #include #include -#include namespace Autotest { namespace Internal { @@ -132,26 +131,20 @@ static QString constructBenchmarkInformation(const QString &metric, double value } TestOutputReader::TestOutputReader(QFutureInterface futureInterface, - QProcess *testApplication, TestType type) - : m_testApplication(testApplication), - m_futureInterface(futureInterface) + QProcess *testApplication) + : m_futureInterface(futureInterface) + , m_testApplication(testApplication) { - if (type == TestTypeQt) - connect(testApplication, &QProcess::readyRead, this, &TestOutputReader::processOutput); - else - connect(testApplication, &QProcess::readyRead, this, &TestOutputReader::processGTestOutput); + connect(m_testApplication, &QProcess::readyRead, this, &TestOutputReader::processOutput); } -enum CDATAMode { - None, - DataTag, - Description, - QtVersion, - QtBuild, - QTestVersion -}; +QtTestOutputReader::QtTestOutputReader(QFutureInterface futureInterface, + QProcess *testApplication) + : TestOutputReader(futureInterface, testApplication) +{ +} -void TestOutputReader::processOutput() +void QtTestOutputReader::processOutput() { if (!m_testApplication || m_testApplication->state() != QProcess::Running) return; @@ -161,115 +154,107 @@ void TestOutputReader::processOutput() QStringLiteral("QtVersion"), QStringLiteral("QtBuild"), QStringLiteral("QTestVersion") }; - static CDATAMode cdataMode = None; - static QString className; - static QString testCase; - static QString dataTag; - static Result::Type result = Result::Invalid; - static QString description; - static QString file; - static int lineNumber = 0; - static QString duration; - static QXmlStreamReader xmlReader; while (m_testApplication->canReadLine()) { - xmlReader.addData(m_testApplication->readLine()); - while (!xmlReader.atEnd()) { - QXmlStreamReader::TokenType token = xmlReader.readNext(); + m_xmlReader.addData(m_testApplication->readLine()); + while (!m_xmlReader.atEnd()) { + if (m_futureInterface.isCanceled()) + return; + QXmlStreamReader::TokenType token = m_xmlReader.readNext(); switch (token) { case QXmlStreamReader::StartDocument: - className.clear(); + m_className.clear(); break; case QXmlStreamReader::EndDocument: - xmlReader.clear(); + m_xmlReader.clear(); return; case QXmlStreamReader::StartElement: { - const QString currentTag = xmlReader.name().toString(); + const QString currentTag = m_xmlReader.name().toString(); if (currentTag == QStringLiteral("TestCase")) { - className = xmlReader.attributes().value(QStringLiteral("name")).toString(); - QTC_ASSERT(!className.isEmpty(), continue); - auto testResult = new QTestResult(className); + m_className = m_xmlReader.attributes().value(QStringLiteral("name")).toString(); + QTC_ASSERT(!m_className.isEmpty(), continue); + auto testResult = new QTestResult(m_className); testResult->setResult(Result::MessageTestCaseStart); - testResult->setDescription(tr("Executing test case %1").arg(className)); + testResult->setDescription(tr("Executing test case %1").arg(m_className)); m_futureInterface.reportResult(testResult); } else if (currentTag == QStringLiteral("TestFunction")) { - testCase = xmlReader.attributes().value(QStringLiteral("name")).toString(); - QTC_ASSERT(!testCase.isEmpty(), continue); + m_testCase = m_xmlReader.attributes().value(QStringLiteral("name")).toString(); + QTC_ASSERT(!m_testCase.isEmpty(), continue); auto testResult = new QTestResult(); testResult->setResult(Result::MessageCurrentTest); - testResult->setDescription(tr("Entering test function %1::%2").arg(className, - testCase)); + testResult->setDescription(tr("Entering test function %1::%2").arg(m_className, + m_testCase)); m_futureInterface.reportResult(testResult); } else if (currentTag == QStringLiteral("Duration")) { - duration = xmlReader.attributes().value(QStringLiteral("msecs")).toString(); - QTC_ASSERT(!duration.isEmpty(), continue); + m_duration = m_xmlReader.attributes().value(QStringLiteral("msecs")).toString(); + QTC_ASSERT(!m_duration.isEmpty(), continue); } else if (currentTag == QStringLiteral("Message") || currentTag == QStringLiteral("Incident")) { - dataTag.clear(); - description.clear(); - duration.clear(); - file.clear(); - result = Result::Invalid; - lineNumber = 0; - const QXmlStreamAttributes &attributes = xmlReader.attributes(); - result = TestResult::resultFromString( + m_dataTag.clear(); + m_description.clear(); + m_duration.clear(); + m_file.clear(); + m_result = Result::Invalid; + m_lineNumber = 0; + const QXmlStreamAttributes &attributes = m_xmlReader.attributes(); + m_result = TestResult::resultFromString( attributes.value(QStringLiteral("type")).toString()); - file = decode(attributes.value(QStringLiteral("file")).toString()); - if (!file.isEmpty()) { + m_file = decode(attributes.value(QStringLiteral("file")).toString()); + if (!m_file.isEmpty()) { const QString base = QFileInfo(m_testApplication->program()).absolutePath(); - file = constructSourceFilePath(base, file, + m_file = constructSourceFilePath(base, m_file, m_testApplication->program()); } - lineNumber = attributes.value(QStringLiteral("line")).toInt(); + m_lineNumber = attributes.value(QStringLiteral("line")).toInt(); } else if (currentTag == QStringLiteral("BenchmarkResult")) { - const QXmlStreamAttributes &attributes = xmlReader.attributes(); + const QXmlStreamAttributes &attributes = m_xmlReader.attributes(); const QString metric = attributes.value(QStringLiteral("metrics")).toString(); const double value = attributes.value(QStringLiteral("value")).toDouble(); const int iterations = attributes.value(QStringLiteral("iterations")).toInt(); - description = constructBenchmarkInformation(metric, value, iterations); - result = Result::Benchmark; + m_description = constructBenchmarkInformation(metric, value, iterations); + m_result = Result::Benchmark; } else if (currentTag == QStringLiteral("DataTag")) { - cdataMode = DataTag; + m_cdataMode = DataTag; } else if (currentTag == QStringLiteral("Description")) { - cdataMode = Description; + m_cdataMode = Description; } else if (currentTag == QStringLiteral("QtVersion")) { - result = Result::MessageInternal; - cdataMode = QtVersion; + m_result = Result::MessageInternal; + m_cdataMode = QtVersion; } else if (currentTag == QStringLiteral("QtBuild")) { - result = Result::MessageInternal; - cdataMode = QtBuild; + m_result = Result::MessageInternal; + m_cdataMode = QtBuild; } else if (currentTag == QStringLiteral("QTestVersion")) { - result = Result::MessageInternal; - cdataMode = QTestVersion; + m_result = Result::MessageInternal; + m_cdataMode = QTestVersion; } break; } case QXmlStreamReader::Characters: { - QStringRef text = xmlReader.text().trimmed(); + QStringRef text = m_xmlReader.text().trimmed(); if (text.isEmpty()) break; - switch (cdataMode) { + switch (m_cdataMode) { case DataTag: - dataTag = text.toString(); + m_dataTag = text.toString(); break; case Description: - if (!description.isEmpty()) - description.append(QLatin1Char('\n')); - description.append(text); + if (!m_description.isEmpty()) + m_description.append(QLatin1Char('\n')); + m_description.append(text); break; case QtVersion: - description = tr("Qt version: %1").arg(text.toString()); + m_description = tr("Qt version: %1").arg(text.toString()); break; case QtBuild: - description = tr("Qt build: %1").arg(text.toString()); + m_description = tr("Qt build: %1").arg(text.toString()); break; case QTestVersion: - description = tr("QTest version: %1").arg(text.toString()); + m_description = tr("QTest version: %1").arg(text.toString()); break; default: QString message = QString::fromLatin1("unexpected cdatamode %1 for text \"%2\"") - .arg(cdataMode) + .arg(m_cdataMode) .arg(text.toString()); QTC_ASSERT(false, qWarning() << message); break; @@ -277,32 +262,32 @@ void TestOutputReader::processOutput() break; } case QXmlStreamReader::EndElement: { - cdataMode = None; - const QStringRef currentTag = xmlReader.name(); + m_cdataMode = None; + const QStringRef currentTag = m_xmlReader.name(); if (currentTag == QStringLiteral("TestFunction")) { - if (!duration.isEmpty()) { - auto testResult = new QTestResult(className); - testResult->setTestCase(testCase); + if (!m_duration.isEmpty()) { + auto testResult = new QTestResult(m_className); + testResult->setTestCase(m_testCase); testResult->setResult(Result::MessageInternal); - testResult->setDescription(tr("Execution took %1 ms.").arg(duration)); + testResult->setDescription(tr("Execution took %1 ms.").arg(m_duration)); m_futureInterface.reportResult(testResult); } m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1); } else if (currentTag == QStringLiteral("TestCase")) { - auto testResult = new QTestResult(className); + auto testResult = new QTestResult(m_className); testResult->setResult(Result::MessageTestCaseEnd); testResult->setDescription( - duration.isEmpty() ? tr("Test finished.") - : tr("Test execution took %1 ms.").arg(duration)); + m_duration.isEmpty() ? tr("Test finished.") + : tr("Test execution took %1 ms.").arg(m_duration)); m_futureInterface.reportResult(testResult); } else if (validEndTags.contains(currentTag.toString())) { - auto testResult = new QTestResult(className); - testResult->setTestCase(testCase); - testResult->setDataTag(dataTag); - testResult->setResult(result); - testResult->setFileName(file); - testResult->setLine(lineNumber); - testResult->setDescription(description); + auto testResult = new QTestResult(m_className); + testResult->setTestCase(m_testCase); + testResult->setDataTag(m_dataTag); + testResult->setResult(m_result); + testResult->setFileName(m_file); + testResult->setLine(m_lineNumber); + testResult->setDescription(m_description); m_futureInterface.reportResult(testResult); } break; @@ -314,7 +299,13 @@ void TestOutputReader::processOutput() } } -void TestOutputReader::processGTestOutput() +GTestOutputReader::GTestOutputReader(QFutureInterface futureInterface, + QProcess *testApplication) + : TestOutputReader(futureInterface, testApplication) +{ +} + +void GTestOutputReader::processOutput() { if (!m_testApplication || m_testApplication->state() != QProcess::Running) return; @@ -326,19 +317,16 @@ void TestOutputReader::processGTestOutput() static QRegExp testSetFail(QStringLiteral("^\\\[ FAILED \\] (.*) \\((.*)\\)$")); static QRegExp disabledTests(QStringLiteral("^ YOU HAVE (\\d+) DISABLED TESTS?$")); - static QString currentTestName; - static QString currentTestSet; - static QString description; - static QByteArray unprocessed; - while (m_testApplication->canReadLine()) { + if (m_futureInterface.isCanceled()) + return; QByteArray read = m_testApplication->readLine(); - if (!unprocessed.isEmpty()) { - read = unprocessed + read; - unprocessed.clear(); + if (!m_unprocessed.isEmpty()) { + read = m_unprocessed + read; + m_unprocessed.clear(); } if (!read.endsWith('\n')) { - unprocessed = read; + m_unprocessed = read; continue; } read.chop(1); // remove the newline from the output @@ -348,13 +336,13 @@ void TestOutputReader::processGTestOutput() continue; if (!line.startsWith(QLatin1Char('['))) { - description.append(line).append(QLatin1Char('\n')); + m_description.append(line).append(QLatin1Char('\n')); if (line.startsWith(QStringLiteral("Note:"))) { auto testResult = new GTestResult(); testResult->setResult(Result::MessageInternal); testResult->setDescription(line); m_futureInterface.reportResult(testResult); - description.clear(); + m_description.clear(); } else if (disabledTests.exactMatch(line)) { auto testResult = new GTestResult(); testResult->setResult(Result::MessageDisabledTests); @@ -362,62 +350,62 @@ void TestOutputReader::processGTestOutput() testResult->setDescription(tr("You have %n disabled test(s).", 0, disabled)); testResult->setLine(disabled); // misuse line property to hold number of disabled m_futureInterface.reportResult(testResult); - description.clear(); + m_description.clear(); } continue; } if (testEnds.exactMatch(line)) { - auto testResult = new GTestResult(currentTestName); - testResult->setTestCase(currentTestSet); + auto testResult = new GTestResult(m_currentTestName); + testResult->setTestCase(m_currentTestSet); testResult->setResult(Result::MessageTestCaseEnd); testResult->setDescription(tr("Test execution took %1").arg(testEnds.cap(2))); m_futureInterface.reportResult(testResult); - currentTestName.clear(); - currentTestSet.clear(); + m_currentTestName.clear(); + m_currentTestSet.clear(); } else if (newTestStarts.exactMatch(line)) { - currentTestName = newTestStarts.cap(1); - auto testResult = new GTestResult(currentTestName); + m_currentTestName = newTestStarts.cap(1); + auto testResult = new GTestResult(m_currentTestName); testResult->setResult(Result::MessageTestCaseStart); - testResult->setDescription(tr("Executing test case %1").arg(currentTestName)); + testResult->setDescription(tr("Executing test case %1").arg(m_currentTestName)); m_futureInterface.reportResult(testResult); } else if (newTestSetStarts.exactMatch(line)) { - currentTestSet = newTestSetStarts.cap(1); + m_currentTestSet = newTestSetStarts.cap(1); auto testResult = new GTestResult(); testResult->setResult(Result::MessageCurrentTest); - testResult->setDescription(tr("Entering test set %1").arg(currentTestSet)); + testResult->setDescription(tr("Entering test set %1").arg(m_currentTestSet)); m_futureInterface.reportResult(testResult); } else if (testSetSuccess.exactMatch(line)) { - auto testResult = new GTestResult(currentTestName); - testResult->setTestCase(currentTestSet); + auto testResult = new GTestResult(m_currentTestName); + testResult->setTestCase(m_currentTestSet); testResult->setResult(Result::Pass); m_futureInterface.reportResult(testResult); - testResult = new GTestResult(currentTestName); - testResult->setTestCase(currentTestSet); + testResult = new GTestResult(m_currentTestName); + testResult->setTestCase(m_currentTestSet); testResult->setResult(Result::MessageInternal); testResult->setDescription(tr("Execution took %1.").arg(testSetSuccess.cap(2))); m_futureInterface.reportResult(testResult); m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1); } else if (testSetFail.exactMatch(line)) { - auto testResult = new GTestResult(currentTestName); - testResult->setTestCase(currentTestSet); + auto testResult = new GTestResult(m_currentTestName); + testResult->setTestCase(m_currentTestSet); testResult->setResult(Result::Fail); - description.chop(1); - testResult->setDescription(description); - int firstColon = description.indexOf(QLatin1Char(':')); + m_description.chop(1); + testResult->setDescription(m_description); + int firstColon = m_description.indexOf(QLatin1Char(':')); if (firstColon != -1) { - int secondColon = description.indexOf(QLatin1Char(':'), firstColon + 1); + int secondColon = m_description.indexOf(QLatin1Char(':'), firstColon + 1); const QString base = QFileInfo(m_testApplication->program()).absolutePath(); - QString file = constructSourceFilePath(base, description.left(firstColon), + QString file = constructSourceFilePath(base, m_description.left(firstColon), m_testApplication->program()); - QString line = description.mid(firstColon + 1, secondColon - firstColon - 1); + QString line = m_description.mid(firstColon + 1, secondColon - firstColon - 1); testResult->setFileName(file); testResult->setLine(line.toInt()); } m_futureInterface.reportResult(testResult); - description.clear(); - testResult = new GTestResult(currentTestName); - testResult->setTestCase(currentTestSet); + m_description.clear(); + testResult = new GTestResult(m_currentTestName); + testResult->setTestCase(m_currentTestSet); testResult->setResult(Result::MessageInternal); testResult->setDescription(tr("Execution took %1.").arg(testSetFail.cap(2))); m_futureInterface.reportResult(testResult); diff --git a/plugins/autotest/testoutputreader.h b/plugins/autotest/testoutputreader.h index 8c9fd789b60..dea58b2c0d5 100644 --- a/plugins/autotest/testoutputreader.h +++ b/plugins/autotest/testoutputreader.h @@ -25,6 +25,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE class QProcess; @@ -38,16 +39,63 @@ class TestOutputReader : public QObject Q_OBJECT public: TestOutputReader(QFutureInterface futureInterface, - QProcess *testApplication, TestType type); + QProcess *testApplication); + +protected: + virtual void processOutput() = 0; + QFutureInterface m_futureInterface; + QProcess *m_testApplication; // not owned +}; + +class QtTestOutputReader : public TestOutputReader +{ +public: + QtTestOutputReader(QFutureInterface futureInterface, + QProcess *testApplication); + +protected: + void processOutput() override; private: - void processOutput(); - void processGTestOutput(); + enum CDATAMode + { + None, + DataTag, + Description, + QtVersion, + QtBuild, + QTestVersion + }; - QProcess *m_testApplication; // not owned - QFutureInterface m_futureInterface; + CDATAMode m_cdataMode = None; + QString m_className; + QString m_testCase; + QString m_dataTag; + Result::Type m_result = Result::Invalid; + QString m_description; + QString m_file; + int m_lineNumber = 0; + QString m_duration; + QXmlStreamReader m_xmlReader; }; +class GTestOutputReader : public TestOutputReader +{ +public: + GTestOutputReader(QFutureInterface futureInterface, + QProcess *testApplication); + +protected: + void processOutput() override; + +private: + QString m_currentTestName; + QString m_currentTestSet; + QString m_description; + QByteArray m_unprocessed; +}; + + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index d8b15c39a30..50fbb053081 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -135,8 +135,15 @@ static void performTestRun(QFutureInterface &futureInterface, futureInterface.setProgressValue(0); foreach (const TestConfiguration *testConfiguration, selectedTests) { - TestOutputReader outputReader(futureInterface, &testProcess, testConfiguration->testType()); - Q_UNUSED(outputReader); + QScopedPointer outputReader; + switch (testConfiguration->testType()) { + case TestTypeQt: + outputReader.reset(new QtTestOutputReader(futureInterface, &testProcess)); + break; + case TestTypeGTest: + outputReader.reset(new GTestOutputReader(futureInterface, &testProcess)); + break; + } if (futureInterface.isCanceled()) break; From ab8970f0effaaefe58c34cb91c6e44c6e4ee4bb2 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 20 Jan 2016 09:38:26 +0100 Subject: [PATCH 195/200] Fix issue with 'Run*'/'Stop' actions... ...when canceling the 'Save Changes' dialog. The test run was canceled before the build, so the 'Run*' and 'Stop' actions stayed in a wrong state forever. Change-Id: I535c50a25c149da32123f832dc6575d1c0fe9643 Reviewed-by: Niels Weber --- plugins/autotest/testrunner.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 50fbb053081..25ea23f6033 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -217,6 +217,13 @@ static void performTestRun(QFutureInterface &futureInterface, void TestRunner::prepareToRunTests() { + ProjectExplorer::Internal::ProjectExplorerSettings projectExplorerSettings = + ProjectExplorer::ProjectExplorerPlugin::projectExplorerSettings(); + if (projectExplorerSettings.buildBeforeDeploy && !projectExplorerSettings.saveBeforeBuild) { + if (!ProjectExplorer::ProjectExplorerPlugin::saveModifiedFiles()) + return; + } + const bool omitRunConfigWarnings = AutotestPlugin::instance()->settings()->omitRunConfigWarn; m_executingTests = true; @@ -250,8 +257,6 @@ void TestRunner::prepareToRunTests() return; } - ProjectExplorer::Internal::ProjectExplorerSettings projectExplorerSettings = - ProjectExplorer::ProjectExplorerPlugin::projectExplorerSettings(); if (!projectExplorerSettings.buildBeforeDeploy) { runTests(); } else { From 180064f8de2ee66a62741e0dc41ea91b5c4f2d36 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 19 Jan 2016 10:50:10 +0100 Subject: [PATCH 196/200] Fix detection of disabled gtests Change-Id: Id5df61d332963f0a94d1f292e4da926faa6e2679 Reviewed-by: Niels Weber --- plugins/autotest/testvisitor.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/autotest/testvisitor.cpp b/plugins/autotest/testvisitor.cpp index 256e679d2fc..c44e7e49804 100644 --- a/plugins/autotest/testvisitor.cpp +++ b/plugins/autotest/testvisitor.cpp @@ -353,6 +353,7 @@ GTestVisitor::GTestVisitor(CPlusPlus::Document::Ptr doc) bool GTestVisitor::visit(CPlusPlus::FunctionDefinitionAST *ast) { + static QString disabledPrefix = QString::fromLatin1("DISABLED_"); if (!ast || !ast->declarator || !ast->declarator->core_declarator) return false; @@ -371,7 +372,8 @@ bool GTestVisitor::visit(CPlusPlus::FunctionDefinitionAST *ast) const QString &testCaseName = m_overview.prettyType(testCaseNameArg->type()); const QString &testName = m_overview.prettyType(testNameArg->type()); - bool disabled = testName.startsWith(QLatin1String("DISABLED_")); + const bool disabled = testName.startsWith(disabledPrefix); + const bool disabledCase = testCaseName.startsWith(disabledPrefix); unsigned line = 0; unsigned column = 0; unsigned token = id->firstToken(); @@ -382,9 +384,10 @@ bool GTestVisitor::visit(CPlusPlus::FunctionDefinitionAST *ast) locationAndType.m_line = line; locationAndType.m_column = column - 1; locationAndType.m_type = TestTreeItem::GTestName; - locationAndType.m_state = disabled ? TestTreeItem::Disabled : TestTreeItem::Enabled; + locationAndType.m_state = (disabled || disabledCase) ? TestTreeItem::Disabled + : TestTreeItem::Enabled; GTestCaseSpec spec; - spec.testCaseName = testCaseName; + spec.testCaseName = disabledCase ? testCaseName.mid(9) : testCaseName; spec.parameterized = TestUtils::isGTestParameterized(prettyName); m_gtestFunctions[spec].append(locationAndType); } From 08011b5deeb5acdb8b88419b7201d05d7ac5b0d6 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 22 Jan 2016 10:37:55 +0100 Subject: [PATCH 197/200] Change license to GPLv3 Change-Id: Ia9fcbc76a56288429c5b99d5cb6eaaf9a7a9f4ff Reviewed-by: Eike Ziller --- plugins/autotest/AutoTest.json.in | 6 +++- plugins/autotest/autotest_global.h | 26 +++++++++------ plugins/autotest/autotest_utils.h | 26 +++++++++------ plugins/autotest/autotestconstants.h | 26 +++++++++------ plugins/autotest/autotesticons.h | 26 +++++++++------ plugins/autotest/autotestplugin.cpp | 26 +++++++++------ plugins/autotest/autotestplugin.h | 26 +++++++++------ plugins/autotest/autotestunittests.cpp | 26 +++++++++------ plugins/autotest/autotestunittests.h | 26 +++++++++------ plugins/autotest/testcodeparser.cpp | 26 +++++++++------ plugins/autotest/testcodeparser.h | 26 +++++++++------ plugins/autotest/testconfiguration.cpp | 26 +++++++++------ plugins/autotest/testconfiguration.h | 26 +++++++++------ plugins/autotest/testinfo.cpp | 26 +++++++++------ plugins/autotest/testinfo.h | 26 +++++++++------ plugins/autotest/testnavigationwidget.cpp | 26 +++++++++------ plugins/autotest/testnavigationwidget.h | 26 +++++++++------ plugins/autotest/testoutputreader.cpp | 26 +++++++++------ plugins/autotest/testoutputreader.h | 26 +++++++++------ plugins/autotest/testresult.cpp | 26 +++++++++------ plugins/autotest/testresult.h | 26 +++++++++------ plugins/autotest/testresultdelegate.cpp | 26 +++++++++------ plugins/autotest/testresultdelegate.h | 26 +++++++++------ plugins/autotest/testresultmodel.cpp | 26 +++++++++------ plugins/autotest/testresultmodel.h | 26 +++++++++------ plugins/autotest/testresultspane.cpp | 26 +++++++++------ plugins/autotest/testresultspane.h | 26 +++++++++------ plugins/autotest/testrunner.cpp | 27 +++++++++------ plugins/autotest/testrunner.h | 26 +++++++++------ plugins/autotest/testsettings.cpp | 26 +++++++++------ plugins/autotest/testsettings.h | 26 +++++++++------ plugins/autotest/testsettingspage.cpp | 26 +++++++++------ plugins/autotest/testsettingspage.h | 26 +++++++++------ plugins/autotest/testtreeitem.cpp | 26 +++++++++------ plugins/autotest/testtreeitem.h | 26 +++++++++------ plugins/autotest/testtreeitemdelegate.cpp | 26 +++++++++------ plugins/autotest/testtreeitemdelegate.h | 26 +++++++++------ plugins/autotest/testtreemodel.cpp | 26 +++++++++------ plugins/autotest/testtreemodel.h | 26 +++++++++------ plugins/autotest/testtreeview.cpp | 26 +++++++++------ plugins/autotest/testtreeview.h | 26 +++++++++------ plugins/autotest/testvisitor.cpp | 26 +++++++++------ plugins/autotest/testvisitor.h | 26 +++++++++------ .../tests/auto/bench/tst_benchtest.cpp | 26 +++++++++------ .../mixed_atp/tests/auto/dummy/tst_foo.cpp | 26 +++++++++------ .../mixed_atp/tests/auto/dummy/tst_foo.h | 26 +++++++++------ .../mixed_atp/tests/auto/gui/tst_guitest.cpp | 26 +++++++++------ .../tests/auto/quickauto/bar/tst_foo.qml | 26 +++++++++------ .../auto/quickauto/notlisted/tst_bla.qml | 26 +++++++++------ .../tests/auto/quickauto/tst_test1.qml | 26 +++++++++------ .../tests/auto/quickauto/tst_test2.qml | 26 +++++++++------ .../tests/auto/quickauto/tst_test3.qml | 26 +++++++++------ .../tests/auto/quickauto2/tst_test1.qml | 26 +++++++++------ .../tests/auto/quickauto2/tst_test2.qml | 26 +++++++++------ .../unit_test/plain/test_plain/tst_simple.cpp | 26 +++++++++------ .../unit_test/simple_gt/tests/gt1/further.cpp | 26 +++++++++------ .../unit_test/simple_gt/tests/gt1/main.cpp | 26 +++++++++------ .../unit_test/simple_gt/tests/gt2/main.cpp | 26 +++++++++------ .../unit_test/simple_gt/tests/gt2/queuetest.h | 26 +++++++++------ .../unit_test/simple_gt/tests/gt3/dummytest.h | 26 +++++++++------ .../unit_test/simple_gt/tests/gt3/main.cpp | 26 +++++++++------ shared/templates/wizards/autotest/wizard.xml | 33 +++++++------------ 62 files changed, 978 insertions(+), 622 deletions(-) diff --git a/plugins/autotest/AutoTest.json.in b/plugins/autotest/AutoTest.json.in index 415347eec15..a11c3b3f788 100644 --- a/plugins/autotest/AutoTest.json.in +++ b/plugins/autotest/AutoTest.json.in @@ -7,7 +7,11 @@ \"Copyright\" : \"(C) 2015 The Qt Company Ltd\", \"License\" : [ \"Commercial Usage\", \"\", -\"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and The Qt Company.\" +\"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and The Qt Company.\", +\"\", +\"GNU General Public License Usage\", +\"\", +\"Alternatively, this file may be used under the terms of the GNU General Public License version 3 as published by the Free Software Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT included in the packaging of this file. Please review the following information to ensure the GNU General Public License requirements will be met: https://www.gnu.org/licenses/gpl-3.0.html.\" ], \"Description\" : \"Auto Test plugin.\", \"Url\" : \"http://www.qt.io\", diff --git a/plugins/autotest/autotest_global.h b/plugins/autotest/autotest_global.h index 1d945af7657..03822d41315 100644 --- a/plugins/autotest/autotest_global.h +++ b/plugins/autotest/autotest_global.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/autotest_utils.h b/plugins/autotest/autotest_utils.h index ee3c464c6a2..ca2b38cea26 100644 --- a/plugins/autotest/autotest_utils.h +++ b/plugins/autotest/autotest_utils.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/autotestconstants.h b/plugins/autotest/autotestconstants.h index 04b4ac04247..5e9f3c56c4d 100644 --- a/plugins/autotest/autotestconstants.h +++ b/plugins/autotest/autotestconstants.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/autotesticons.h b/plugins/autotest/autotesticons.h index 8454b95f405..88c929dc977 100644 --- a/plugins/autotest/autotesticons.h +++ b/plugins/autotest/autotesticons.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index c024aa2bd25..7ab0a8f1d95 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/autotestplugin.h b/plugins/autotest/autotestplugin.h index b7a02d89e77..18ffbaf4ed4 100644 --- a/plugins/autotest/autotestplugin.h +++ b/plugins/autotest/autotestplugin.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/autotestunittests.cpp b/plugins/autotest/autotestunittests.cpp index 95bc954502f..6e58f877200 100644 --- a/plugins/autotest/autotestunittests.cpp +++ b/plugins/autotest/autotestunittests.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/autotestunittests.h b/plugins/autotest/autotestunittests.h index ddd5249739c..b5e808d3ce8 100644 --- a/plugins/autotest/autotestunittests.h +++ b/plugins/autotest/autotestunittests.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index 556fc735e2a..2ac2a1cb874 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h index 5861009e5ac..0b3d76ba6cc 100644 --- a/plugins/autotest/testcodeparser.h +++ b/plugins/autotest/testcodeparser.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testconfiguration.cpp b/plugins/autotest/testconfiguration.cpp index dd8a2c3b066..063aa5980ea 100644 --- a/plugins/autotest/testconfiguration.cpp +++ b/plugins/autotest/testconfiguration.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testconfiguration.h b/plugins/autotest/testconfiguration.h index 7fb915fbb55..632ce69b720 100644 --- a/plugins/autotest/testconfiguration.h +++ b/plugins/autotest/testconfiguration.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testinfo.cpp b/plugins/autotest/testinfo.cpp index 7385f159884..859df4ee3af 100644 --- a/plugins/autotest/testinfo.cpp +++ b/plugins/autotest/testinfo.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testinfo.h b/plugins/autotest/testinfo.h index 056f019a9bb..5e8e9f355fd 100644 --- a/plugins/autotest/testinfo.h +++ b/plugins/autotest/testinfo.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp index 914290e36b9..a8432e70bee 100644 --- a/plugins/autotest/testnavigationwidget.cpp +++ b/plugins/autotest/testnavigationwidget.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testnavigationwidget.h b/plugins/autotest/testnavigationwidget.h index ef281308170..5f92909b93d 100644 --- a/plugins/autotest/testnavigationwidget.h +++ b/plugins/autotest/testnavigationwidget.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testoutputreader.cpp b/plugins/autotest/testoutputreader.cpp index 609c139e123..2a97f0c818a 100644 --- a/plugins/autotest/testoutputreader.cpp +++ b/plugins/autotest/testoutputreader.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testoutputreader.h b/plugins/autotest/testoutputreader.h index dea58b2c0d5..9a50e605573 100644 --- a/plugins/autotest/testoutputreader.h +++ b/plugins/autotest/testoutputreader.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp index ba75fb5246e..a7f3cc34638 100644 --- a/plugins/autotest/testresult.cpp +++ b/plugins/autotest/testresult.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index b4226da5728..91e380c9c35 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp index a9a59b7f34e..305b6aaff82 100644 --- a/plugins/autotest/testresultdelegate.cpp +++ b/plugins/autotest/testresultdelegate.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testresultdelegate.h b/plugins/autotest/testresultdelegate.h index 9df661ab5b5..ceaecdc8c62 100644 --- a/plugins/autotest/testresultdelegate.h +++ b/plugins/autotest/testresultdelegate.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp index a3dac8e3192..835850fe733 100644 --- a/plugins/autotest/testresultmodel.cpp +++ b/plugins/autotest/testresultmodel.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testresultmodel.h b/plugins/autotest/testresultmodel.h index 782f7223b3e..34f117e5381 100644 --- a/plugins/autotest/testresultmodel.h +++ b/plugins/autotest/testresultmodel.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 0114279c555..e46c9e7809f 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h index 5fbb71413e2..a50f75e9f46 100644 --- a/plugins/autotest/testresultspane.h +++ b/plugins/autotest/testresultspane.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp index 25ea23f6033..4914d6d26c9 100644 --- a/plugins/autotest/testrunner.cpp +++ b/plugins/autotest/testrunner.cpp @@ -1,21 +1,28 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ + #include "testrunner.h" #include "autotestconstants.h" diff --git a/plugins/autotest/testrunner.h b/plugins/autotest/testrunner.h index c3cd89ef60d..c51edb95b11 100644 --- a/plugins/autotest/testrunner.h +++ b/plugins/autotest/testrunner.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testsettings.cpp b/plugins/autotest/testsettings.cpp index bb5bcd61ece..e4c38d9d3d9 100644 --- a/plugins/autotest/testsettings.cpp +++ b/plugins/autotest/testsettings.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testsettings.h b/plugins/autotest/testsettings.h index 8ef368e8040..30b7b8f54b8 100644 --- a/plugins/autotest/testsettings.h +++ b/plugins/autotest/testsettings.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testsettingspage.cpp b/plugins/autotest/testsettingspage.cpp index 643704649ce..fcc5508e70d 100644 --- a/plugins/autotest/testsettingspage.cpp +++ b/plugins/autotest/testsettingspage.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testsettingspage.h b/plugins/autotest/testsettingspage.h index 3e98c8413de..c41929c6677 100644 --- a/plugins/autotest/testsettingspage.h +++ b/plugins/autotest/testsettingspage.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index e6ea3a89131..2011b4412cc 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index bc6038809c8..325486b6694 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testtreeitemdelegate.cpp b/plugins/autotest/testtreeitemdelegate.cpp index e17e6029c97..e5cc237aa56 100644 --- a/plugins/autotest/testtreeitemdelegate.cpp +++ b/plugins/autotest/testtreeitemdelegate.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testtreeitemdelegate.h b/plugins/autotest/testtreeitemdelegate.h index d4777f438cb..0391ea28d30 100644 --- a/plugins/autotest/testtreeitemdelegate.h +++ b/plugins/autotest/testtreeitemdelegate.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 19f47e40006..65b7759315e 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index c8eefd042fc..b63c29c5a62 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testtreeview.cpp b/plugins/autotest/testtreeview.cpp index 39105b6bdcb..b6c8541450a 100644 --- a/plugins/autotest/testtreeview.cpp +++ b/plugins/autotest/testtreeview.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testtreeview.h b/plugins/autotest/testtreeview.h index c9a4d9f9ff1..a75c2fdaa7c 100644 --- a/plugins/autotest/testtreeview.h +++ b/plugins/autotest/testtreeview.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testvisitor.cpp b/plugins/autotest/testvisitor.cpp index c44e7e49804..40819dfccdc 100644 --- a/plugins/autotest/testvisitor.cpp +++ b/plugins/autotest/testvisitor.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/testvisitor.h b/plugins/autotest/testvisitor.h index c2129d3f1d2..b4fb28329f8 100644 --- a/plugins/autotest/testvisitor.h +++ b/plugins/autotest/testvisitor.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp b/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp index bd00dda5637..2b200f254fb 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp index caac56ff037..1646cf14500 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include "tst_foo.h" diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h index f9b95a2bd7b..1f70867f807 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #ifndef FOO_H_INCLUDED diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp b/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp index 5681ce1fd37..1f7fce915b4 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml index da2196e79d7..0653fcda9c4 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ import QtQuick 2.0 diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml index b6f04f5389d..52b3837818c 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ import QtQuick 2.0 diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml index 67d2965452e..fa609a9aced 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ import QtQuick 2.0 diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml index 02331ec9a0a..d0115c5dd74 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ import QtQuick 2.0 diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml index 8d362d1dd95..f28af4f77e9 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ import QtQuick 2.0 diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml index 67d2965452e..fa609a9aced 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ import QtQuick 2.0 diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml index 1c3465b1c32..8a7d4dd9b47 100644 --- a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml +++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ import QtQuick 2.0 diff --git a/plugins/autotest/unit_test/plain/test_plain/tst_simple.cpp b/plugins/autotest/unit_test/plain/test_plain/tst_simple.cpp index 864883f75ba..6f7ee9f1386 100644 --- a/plugins/autotest/unit_test/plain/test_plain/tst_simple.cpp +++ b/plugins/autotest/unit_test/plain/test_plain/tst_simple.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include "tst_simple.h" diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt1/further.cpp b/plugins/autotest/unit_test/simple_gt/tests/gt1/further.cpp index 559bde41635..977fda04da5 100644 --- a/plugins/autotest/unit_test/simple_gt/tests/gt1/further.cpp +++ b/plugins/autotest/unit_test/simple_gt/tests/gt1/further.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt1/main.cpp b/plugins/autotest/unit_test/simple_gt/tests/gt1/main.cpp index 64e386b8862..a4a394b3105 100644 --- a/plugins/autotest/unit_test/simple_gt/tests/gt1/main.cpp +++ b/plugins/autotest/unit_test/simple_gt/tests/gt1/main.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt2/main.cpp b/plugins/autotest/unit_test/simple_gt/tests/gt2/main.cpp index 2bda4c12d3f..32c52f646c6 100644 --- a/plugins/autotest/unit_test/simple_gt/tests/gt2/main.cpp +++ b/plugins/autotest/unit_test/simple_gt/tests/gt2/main.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h b/plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h index aebabf0f336..2ba330d6f68 100644 --- a/plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h +++ b/plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt3/dummytest.h b/plugins/autotest/unit_test/simple_gt/tests/gt3/dummytest.h index b8fac8e799d..f92c1a1b160 100644 --- a/plugins/autotest/unit_test/simple_gt/tests/gt3/dummytest.h +++ b/plugins/autotest/unit_test/simple_gt/tests/gt3/dummytest.h @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp b/plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp index 088506ec555..4f048fa177f 100644 --- a/plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp +++ b/plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp @@ -1,19 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at -** http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Creator Enterprise Auto Test Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include diff --git a/shared/templates/wizards/autotest/wizard.xml b/shared/templates/wizards/autotest/wizard.xml index a190405d389..12f0c1e0075 100644 --- a/shared/templates/wizards/autotest/wizard.xml +++ b/shared/templates/wizards/autotest/wizard.xml @@ -2,8 +2,8 @@ Date: Fri, 22 Jan 2016 10:43:28 +0100 Subject: [PATCH 198/200] Remove licensechecker dependency Change-Id: Ie15e903f3e7f0fde3c7e4127584c573741aee19f Reviewed-by: Eike Ziller --- plugins/autotest/autotest.pro | 3 --- plugins/autotest/autotest_dependencies.pri | 2 -- plugins/autotest/autotestplugin.cpp | 22 ---------------------- 3 files changed, 27 deletions(-) diff --git a/plugins/autotest/autotest.pro b/plugins/autotest/autotest.pro index 45ab5582909..057060f2fac 100644 --- a/plugins/autotest/autotest.pro +++ b/plugins/autotest/autotest.pro @@ -1,13 +1,10 @@ TARGET = AutoTest TEMPLATE = lib -PROVIDER = Digia - include(../../qtcreatorplugin.pri) include(autotest_dependencies.pri) DEFINES += AUTOTEST_LIBRARY -CONFIG(licensechecker): DEFINES += LICENSECHECKER SOURCES += \ testtreeview.cpp \ diff --git a/plugins/autotest/autotest_dependencies.pri b/plugins/autotest/autotest_dependencies.pri index 9410d779504..ab2e02f054d 100644 --- a/plugins/autotest/autotest_dependencies.pri +++ b/plugins/autotest/autotest_dependencies.pri @@ -6,8 +6,6 @@ QTC_PLUGIN_DEPENDS += \ cpptools \ qmljstools -CONFIG(licensechecker): QTC_PLUGIN_DEPENDS += licensechecker - QTC_LIB_DEPENDS += \ cplusplus \ qmljs \ diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp index 7ab0a8f1d95..83f3be8da46 100644 --- a/plugins/autotest/autotestplugin.cpp +++ b/plugins/autotest/autotestplugin.cpp @@ -44,10 +44,6 @@ #include -#ifdef LICENSECHECKER -# include -#endif - #include #include #include @@ -95,21 +91,6 @@ QSharedPointer AutotestPlugin::settings() const return m_settings; } -bool AutotestPlugin::checkLicense() -{ -#ifdef LICENSECHECKER - LicenseChecker::LicenseCheckerPlugin *licenseChecker - = ExtensionSystem::PluginManager::getObject(); - - if (!licenseChecker || !licenseChecker->hasValidLicense()) { - qWarning() << "Invalid license, disabling Qt Creator Enterprise Auto Test Add-on."; - return false; - } else if (!licenseChecker->enterpriseFeatures()) - return false; -#endif // LICENSECHECKER - return true; -} - void AutotestPlugin::initializeMenuEntries() { ActionContainer *menu = ActionManager::createMenu(Constants::MENU_ID); @@ -147,9 +128,6 @@ bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorStri Q_UNUSED(arguments) Q_UNUSED(errorString) - if (!checkLicense()) - return true; - initializeMenuEntries(); m_settings->fromSettings(ICore::settings()); From 15b4e6fc91f3c9a50e695d1c81933ba132efe9b6 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 22 Jan 2016 10:46:45 +0100 Subject: [PATCH 199/200] Delete unneeded and prepare directory structure... ...to get plugin's repository more easily integrated into QC's repository. Change-Id: I10243bb4283623ae951e799feacaa15915678e04 Reviewed-by: Eike Ziller --- autotest.pro | 6 ------ qtcreatorplugin.pri | 8 -------- .../templates/wizards/autotest/auto.pro | 0 .../templates/wizards/autotest/autotest_24.png | Bin .../templates/wizards/autotest/main.cpp | 0 .../templates/wizards/autotest/src.pro | 0 .../templates/wizards/autotest/tests.pro | 0 .../templates/wizards/autotest/tmp.pro | 0 .../templates/wizards/autotest/tst.pro | 0 .../templates/wizards/autotest/tst_src.cpp | 0 .../templates/wizards/autotest/wizard.xml | 0 shared/shared.pro | 17 ----------------- .../plugins}/autotest/AutoTest.json.in | 0 {plugins => src/plugins}/autotest/autotest.pro | 0 {plugins => src/plugins}/autotest/autotest.qbs | 0 {plugins => src/plugins}/autotest/autotest.qrc | 0 .../autotest/autotest_dependencies.pri | 0 .../plugins}/autotest/autotest_global.h | 0 .../plugins}/autotest/autotest_utils.h | 0 .../plugins}/autotest/autotestconstants.h | 0 .../plugins}/autotest/autotesticons.h | 0 .../plugins}/autotest/autotestplugin.cpp | 0 .../plugins}/autotest/autotestplugin.h | 0 .../plugins}/autotest/autotestunittests.cpp | 0 .../plugins}/autotest/autotestunittests.h | 0 .../plugins}/autotest/autotestunittests.qrc | 0 .../plugins}/autotest/images/autotest.png | Bin .../plugins}/autotest/images/benchmark.png | Bin .../autotest/images/blacklisted_fail.png | Bin .../autotest/images/blacklisted_pass.png | Bin .../plugins}/autotest/images/class.png | Bin .../plugins}/autotest/images/collapse.png | Bin .../plugins}/autotest/images/collapse@2x.png | Bin .../plugins}/autotest/images/data.png | Bin .../plugins}/autotest/images/debug.png | Bin .../plugins}/autotest/images/expand.png | Bin .../plugins}/autotest/images/expand@2x.png | Bin .../plugins}/autotest/images/fail.png | Bin .../plugins}/autotest/images/fatal.png | Bin .../plugins}/autotest/images/func.png | Bin .../plugins}/autotest/images/leafsort.png | Bin .../plugins}/autotest/images/leafsort@2x.png | Bin .../plugins}/autotest/images/pass.png | Bin .../autotest/images/runselected_boxes.png | Bin .../autotest/images/runselected_boxes@2x.png | Bin .../autotest/images/runselected_tickmarks.png | Bin .../images/runselected_tickmarks@2x.png | Bin .../plugins}/autotest/images/skip.png | Bin .../plugins}/autotest/images/sort.png | Bin .../plugins}/autotest/images/sort@2x.png | Bin .../plugins}/autotest/images/warn.png | Bin .../plugins}/autotest/images/xfail.png | Bin .../plugins}/autotest/images/xpass.png | Bin .../plugins}/autotest/testcodeparser.cpp | 0 .../plugins}/autotest/testcodeparser.h | 0 .../plugins}/autotest/testconfiguration.cpp | 0 .../plugins}/autotest/testconfiguration.h | 0 {plugins => src/plugins}/autotest/testinfo.cpp | 0 {plugins => src/plugins}/autotest/testinfo.h | 0 .../plugins}/autotest/testnavigationwidget.cpp | 0 .../plugins}/autotest/testnavigationwidget.h | 0 .../plugins}/autotest/testoutputreader.cpp | 0 .../plugins}/autotest/testoutputreader.h | 0 .../plugins}/autotest/testresult.cpp | 0 {plugins => src/plugins}/autotest/testresult.h | 0 .../plugins}/autotest/testresultdelegate.cpp | 0 .../plugins}/autotest/testresultdelegate.h | 0 .../plugins}/autotest/testresultmodel.cpp | 0 .../plugins}/autotest/testresultmodel.h | 0 .../plugins}/autotest/testresultspane.cpp | 0 .../plugins}/autotest/testresultspane.h | 0 .../plugins}/autotest/testrunner.cpp | 0 {plugins => src/plugins}/autotest/testrunner.h | 0 .../plugins}/autotest/testsettings.cpp | 0 .../plugins}/autotest/testsettings.h | 0 .../plugins}/autotest/testsettingspage.cpp | 0 .../plugins}/autotest/testsettingspage.h | 0 .../plugins}/autotest/testsettingspage.ui | 0 .../plugins}/autotest/testtreeitem.cpp | 0 .../plugins}/autotest/testtreeitem.h | 0 .../plugins}/autotest/testtreeitemdelegate.cpp | 0 .../plugins}/autotest/testtreeitemdelegate.h | 0 .../plugins}/autotest/testtreemodel.cpp | 0 .../plugins}/autotest/testtreemodel.h | 0 .../plugins}/autotest/testtreeview.cpp | 0 .../plugins}/autotest/testtreeview.h | 0 .../plugins}/autotest/testvisitor.cpp | 0 .../plugins}/autotest/testvisitor.h | 0 .../autotest/unit_test/mixed_atp/mixed_atp.pro | 0 .../autotest/unit_test/mixed_atp/mixed_atp.qbs | 0 .../autotest/unit_test/mixed_atp/src/main.cpp | 0 .../autotest/unit_test/mixed_atp/src/src.pro | 0 .../autotest/unit_test/mixed_atp/src/src.qbs | 0 .../unit_test/mixed_atp/tests/auto/auto.pro | 0 .../unit_test/mixed_atp/tests/auto/auto.qbs | 0 .../mixed_atp/tests/auto/bench/bench.pro | 0 .../mixed_atp/tests/auto/bench/bench.qbs | 0 .../tests/auto/bench/tst_benchtest.cpp | 0 .../mixed_atp/tests/auto/dummy/dummy.pro | 0 .../mixed_atp/tests/auto/dummy/dummy.qbs | 0 .../mixed_atp/tests/auto/dummy/tst_foo.cpp | 0 .../mixed_atp/tests/auto/dummy/tst_foo.h | 0 .../unit_test/mixed_atp/tests/auto/gui/gui.pro | 0 .../unit_test/mixed_atp/tests/auto/gui/gui.qbs | 0 .../mixed_atp/tests/auto/gui/tst_guitest.cpp | 0 .../tests/auto/quickauto/TestDummy.qml | 0 .../tests/auto/quickauto/bar/tst_foo.qml | 0 .../mixed_atp/tests/auto/quickauto/main.cpp | 0 .../tests/auto/quickauto/notlisted/tst_bla.qml | 0 .../tests/auto/quickauto/quickauto.pro | 0 .../tests/auto/quickauto/quickauto.qbs | 0 .../tests/auto/quickauto/tst_test1.qml | 0 .../tests/auto/quickauto/tst_test2.qml | 0 .../tests/auto/quickauto/tst_test3.qml | 0 .../mixed_atp/tests/auto/quickauto2/main.cpp | 0 .../tests/auto/quickauto2/quickauto2.pro | 0 .../tests/auto/quickauto2/quickauto2.qbs | 0 .../tests/auto/quickauto2/tst_test1.qml | 0 .../tests/auto/quickauto2/tst_test2.qml | 0 .../unit_test/mixed_atp/tests/tests.pro | 0 .../unit_test/mixed_atp/tests/tests.qbs | 0 .../autotest/unit_test/plain/plain.pro | 0 .../autotest/unit_test/plain/plain.qbs | 0 .../unit_test/plain/test_plain/test_plain.pro | 0 .../unit_test/plain/test_plain/test_plain.qbs | 0 .../unit_test/plain/test_plain/tst_simple.cpp | 0 .../unit_test/plain/test_plain/tst_simple.h | 0 .../autotest/unit_test/simple_gt/simple_gt.pro | 0 .../autotest/unit_test/simple_gt/src/main.cpp | 0 .../autotest/unit_test/simple_gt/src/src.pro | 0 .../unit_test/simple_gt/tests/gt1/further.cpp | 0 .../unit_test/simple_gt/tests/gt1/gt1.pro | 0 .../unit_test/simple_gt/tests/gt1/main.cpp | 0 .../unit_test/simple_gt/tests/gt2/gt2.pro | 0 .../unit_test/simple_gt/tests/gt2/main.cpp | 0 .../unit_test/simple_gt/tests/gt2/queuetest.h | 0 .../unit_test/simple_gt/tests/gt3/dummytest.h | 0 .../unit_test/simple_gt/tests/gt3/gt3.pro | 0 .../unit_test/simple_gt/tests/gt3/main.cpp | 0 .../simple_gt/tests/gtest_dependency.pri | 0 .../unit_test/simple_gt/tests/tests.pro | 0 141 files changed, 31 deletions(-) delete mode 100644 autotest.pro delete mode 100644 qtcreatorplugin.pri rename shared/{ => qtcreator}/templates/wizards/autotest/auto.pro (100%) rename shared/{ => qtcreator}/templates/wizards/autotest/autotest_24.png (100%) rename shared/{ => qtcreator}/templates/wizards/autotest/main.cpp (100%) rename shared/{ => qtcreator}/templates/wizards/autotest/src.pro (100%) rename shared/{ => qtcreator}/templates/wizards/autotest/tests.pro (100%) rename shared/{ => qtcreator}/templates/wizards/autotest/tmp.pro (100%) rename shared/{ => qtcreator}/templates/wizards/autotest/tst.pro (100%) rename shared/{ => qtcreator}/templates/wizards/autotest/tst_src.cpp (100%) rename shared/{ => qtcreator}/templates/wizards/autotest/wizard.xml (100%) delete mode 100644 shared/shared.pro rename {plugins => src/plugins}/autotest/AutoTest.json.in (100%) rename {plugins => src/plugins}/autotest/autotest.pro (100%) rename {plugins => src/plugins}/autotest/autotest.qbs (100%) rename {plugins => src/plugins}/autotest/autotest.qrc (100%) rename {plugins => src/plugins}/autotest/autotest_dependencies.pri (100%) rename {plugins => src/plugins}/autotest/autotest_global.h (100%) rename {plugins => src/plugins}/autotest/autotest_utils.h (100%) rename {plugins => src/plugins}/autotest/autotestconstants.h (100%) rename {plugins => src/plugins}/autotest/autotesticons.h (100%) rename {plugins => src/plugins}/autotest/autotestplugin.cpp (100%) rename {plugins => src/plugins}/autotest/autotestplugin.h (100%) rename {plugins => src/plugins}/autotest/autotestunittests.cpp (100%) rename {plugins => src/plugins}/autotest/autotestunittests.h (100%) rename {plugins => src/plugins}/autotest/autotestunittests.qrc (100%) rename {plugins => src/plugins}/autotest/images/autotest.png (100%) rename {plugins => src/plugins}/autotest/images/benchmark.png (100%) rename {plugins => src/plugins}/autotest/images/blacklisted_fail.png (100%) rename {plugins => src/plugins}/autotest/images/blacklisted_pass.png (100%) rename {plugins => src/plugins}/autotest/images/class.png (100%) rename {plugins => src/plugins}/autotest/images/collapse.png (100%) rename {plugins => src/plugins}/autotest/images/collapse@2x.png (100%) rename {plugins => src/plugins}/autotest/images/data.png (100%) rename {plugins => src/plugins}/autotest/images/debug.png (100%) rename {plugins => src/plugins}/autotest/images/expand.png (100%) rename {plugins => src/plugins}/autotest/images/expand@2x.png (100%) rename {plugins => src/plugins}/autotest/images/fail.png (100%) rename {plugins => src/plugins}/autotest/images/fatal.png (100%) rename {plugins => src/plugins}/autotest/images/func.png (100%) rename {plugins => src/plugins}/autotest/images/leafsort.png (100%) rename {plugins => src/plugins}/autotest/images/leafsort@2x.png (100%) rename {plugins => src/plugins}/autotest/images/pass.png (100%) rename {plugins => src/plugins}/autotest/images/runselected_boxes.png (100%) rename {plugins => src/plugins}/autotest/images/runselected_boxes@2x.png (100%) rename {plugins => src/plugins}/autotest/images/runselected_tickmarks.png (100%) rename {plugins => src/plugins}/autotest/images/runselected_tickmarks@2x.png (100%) rename {plugins => src/plugins}/autotest/images/skip.png (100%) rename {plugins => src/plugins}/autotest/images/sort.png (100%) rename {plugins => src/plugins}/autotest/images/sort@2x.png (100%) rename {plugins => src/plugins}/autotest/images/warn.png (100%) rename {plugins => src/plugins}/autotest/images/xfail.png (100%) rename {plugins => src/plugins}/autotest/images/xpass.png (100%) rename {plugins => src/plugins}/autotest/testcodeparser.cpp (100%) rename {plugins => src/plugins}/autotest/testcodeparser.h (100%) rename {plugins => src/plugins}/autotest/testconfiguration.cpp (100%) rename {plugins => src/plugins}/autotest/testconfiguration.h (100%) rename {plugins => src/plugins}/autotest/testinfo.cpp (100%) rename {plugins => src/plugins}/autotest/testinfo.h (100%) rename {plugins => src/plugins}/autotest/testnavigationwidget.cpp (100%) rename {plugins => src/plugins}/autotest/testnavigationwidget.h (100%) rename {plugins => src/plugins}/autotest/testoutputreader.cpp (100%) rename {plugins => src/plugins}/autotest/testoutputreader.h (100%) rename {plugins => src/plugins}/autotest/testresult.cpp (100%) rename {plugins => src/plugins}/autotest/testresult.h (100%) rename {plugins => src/plugins}/autotest/testresultdelegate.cpp (100%) rename {plugins => src/plugins}/autotest/testresultdelegate.h (100%) rename {plugins => src/plugins}/autotest/testresultmodel.cpp (100%) rename {plugins => src/plugins}/autotest/testresultmodel.h (100%) rename {plugins => src/plugins}/autotest/testresultspane.cpp (100%) rename {plugins => src/plugins}/autotest/testresultspane.h (100%) rename {plugins => src/plugins}/autotest/testrunner.cpp (100%) rename {plugins => src/plugins}/autotest/testrunner.h (100%) rename {plugins => src/plugins}/autotest/testsettings.cpp (100%) rename {plugins => src/plugins}/autotest/testsettings.h (100%) rename {plugins => src/plugins}/autotest/testsettingspage.cpp (100%) rename {plugins => src/plugins}/autotest/testsettingspage.h (100%) rename {plugins => src/plugins}/autotest/testsettingspage.ui (100%) rename {plugins => src/plugins}/autotest/testtreeitem.cpp (100%) rename {plugins => src/plugins}/autotest/testtreeitem.h (100%) rename {plugins => src/plugins}/autotest/testtreeitemdelegate.cpp (100%) rename {plugins => src/plugins}/autotest/testtreeitemdelegate.h (100%) rename {plugins => src/plugins}/autotest/testtreemodel.cpp (100%) rename {plugins => src/plugins}/autotest/testtreemodel.h (100%) rename {plugins => src/plugins}/autotest/testtreeview.cpp (100%) rename {plugins => src/plugins}/autotest/testtreeview.h (100%) rename {plugins => src/plugins}/autotest/testvisitor.cpp (100%) rename {plugins => src/plugins}/autotest/testvisitor.h (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/mixed_atp.pro (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/mixed_atp.qbs (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/src/main.cpp (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/src/src.pro (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/src/src.qbs (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/auto.pro (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/auto.qbs (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/bench/bench.pro (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/bench/bench.qbs (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.pro (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.qbs (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/gui/gui.pro (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/gui/gui.qbs (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/quickauto/TestDummy.qml (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/quickauto/main.cpp (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.pro (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.qbs (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/quickauto2/main.cpp (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.pro (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/tests.pro (100%) rename {plugins => src/plugins}/autotest/unit_test/mixed_atp/tests/tests.qbs (100%) rename {plugins => src/plugins}/autotest/unit_test/plain/plain.pro (100%) rename {plugins => src/plugins}/autotest/unit_test/plain/plain.qbs (100%) rename {plugins => src/plugins}/autotest/unit_test/plain/test_plain/test_plain.pro (100%) rename {plugins => src/plugins}/autotest/unit_test/plain/test_plain/test_plain.qbs (100%) rename {plugins => src/plugins}/autotest/unit_test/plain/test_plain/tst_simple.cpp (100%) rename {plugins => src/plugins}/autotest/unit_test/plain/test_plain/tst_simple.h (100%) rename {plugins => src/plugins}/autotest/unit_test/simple_gt/simple_gt.pro (100%) rename {plugins => src/plugins}/autotest/unit_test/simple_gt/src/main.cpp (100%) rename {plugins => src/plugins}/autotest/unit_test/simple_gt/src/src.pro (100%) rename {plugins => src/plugins}/autotest/unit_test/simple_gt/tests/gt1/further.cpp (100%) rename {plugins => src/plugins}/autotest/unit_test/simple_gt/tests/gt1/gt1.pro (100%) rename {plugins => src/plugins}/autotest/unit_test/simple_gt/tests/gt1/main.cpp (100%) rename {plugins => src/plugins}/autotest/unit_test/simple_gt/tests/gt2/gt2.pro (100%) rename {plugins => src/plugins}/autotest/unit_test/simple_gt/tests/gt2/main.cpp (100%) rename {plugins => src/plugins}/autotest/unit_test/simple_gt/tests/gt2/queuetest.h (100%) rename {plugins => src/plugins}/autotest/unit_test/simple_gt/tests/gt3/dummytest.h (100%) rename {plugins => src/plugins}/autotest/unit_test/simple_gt/tests/gt3/gt3.pro (100%) rename {plugins => src/plugins}/autotest/unit_test/simple_gt/tests/gt3/main.cpp (100%) rename {plugins => src/plugins}/autotest/unit_test/simple_gt/tests/gtest_dependency.pri (100%) rename {plugins => src/plugins}/autotest/unit_test/simple_gt/tests/tests.pro (100%) diff --git a/autotest.pro b/autotest.pro deleted file mode 100644 index 77543b34a51..00000000000 --- a/autotest.pro +++ /dev/null @@ -1,6 +0,0 @@ -TEMPLATE = subdirs -CONFIG += ordered - -SUBDIRS += plugins/autotest shared - -QMAKE_EXTRA_TARGETS = docs install_docs # dummy targets for consistency diff --git a/qtcreatorplugin.pri b/qtcreatorplugin.pri deleted file mode 100644 index 190dbed1c3b..00000000000 --- a/qtcreatorplugin.pri +++ /dev/null @@ -1,8 +0,0 @@ -isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE=$$(QTC_SOURCE) -isEmpty(IDE_BUILD_TREE): IDE_BUILD_TREE=$$(QTC_BUILD) - -isEmpty(IDE_SOURCE_TREE):error(Set QTC_SOURCE environment variable) -isEmpty(IDE_BUILD_TREE):error(Set QTC_BUILD environment variable) - -INCLUDEPATH+= $$PWD/plugins -include($$IDE_SOURCE_TREE/src/qtcreatorplugin.pri) diff --git a/shared/templates/wizards/autotest/auto.pro b/shared/qtcreator/templates/wizards/autotest/auto.pro similarity index 100% rename from shared/templates/wizards/autotest/auto.pro rename to shared/qtcreator/templates/wizards/autotest/auto.pro diff --git a/shared/templates/wizards/autotest/autotest_24.png b/shared/qtcreator/templates/wizards/autotest/autotest_24.png similarity index 100% rename from shared/templates/wizards/autotest/autotest_24.png rename to shared/qtcreator/templates/wizards/autotest/autotest_24.png diff --git a/shared/templates/wizards/autotest/main.cpp b/shared/qtcreator/templates/wizards/autotest/main.cpp similarity index 100% rename from shared/templates/wizards/autotest/main.cpp rename to shared/qtcreator/templates/wizards/autotest/main.cpp diff --git a/shared/templates/wizards/autotest/src.pro b/shared/qtcreator/templates/wizards/autotest/src.pro similarity index 100% rename from shared/templates/wizards/autotest/src.pro rename to shared/qtcreator/templates/wizards/autotest/src.pro diff --git a/shared/templates/wizards/autotest/tests.pro b/shared/qtcreator/templates/wizards/autotest/tests.pro similarity index 100% rename from shared/templates/wizards/autotest/tests.pro rename to shared/qtcreator/templates/wizards/autotest/tests.pro diff --git a/shared/templates/wizards/autotest/tmp.pro b/shared/qtcreator/templates/wizards/autotest/tmp.pro similarity index 100% rename from shared/templates/wizards/autotest/tmp.pro rename to shared/qtcreator/templates/wizards/autotest/tmp.pro diff --git a/shared/templates/wizards/autotest/tst.pro b/shared/qtcreator/templates/wizards/autotest/tst.pro similarity index 100% rename from shared/templates/wizards/autotest/tst.pro rename to shared/qtcreator/templates/wizards/autotest/tst.pro diff --git a/shared/templates/wizards/autotest/tst_src.cpp b/shared/qtcreator/templates/wizards/autotest/tst_src.cpp similarity index 100% rename from shared/templates/wizards/autotest/tst_src.cpp rename to shared/qtcreator/templates/wizards/autotest/tst_src.cpp diff --git a/shared/templates/wizards/autotest/wizard.xml b/shared/qtcreator/templates/wizards/autotest/wizard.xml similarity index 100% rename from shared/templates/wizards/autotest/wizard.xml rename to shared/qtcreator/templates/wizards/autotest/wizard.xml diff --git a/shared/shared.pro b/shared/shared.pro deleted file mode 100644 index 541044da119..00000000000 --- a/shared/shared.pro +++ /dev/null @@ -1,17 +0,0 @@ -isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE = $$(QTC_SOURCE) -isEmpty(IDE_BUILD_TREE): IDE_BUILD_TREE = $$(QTC_BUILD) -isEmpty(IDE_SOURCE_TREE): error("Set QTC_SOURCE environment variable") -isEmpty(IDE_BUILD_TREE): error("Set QTC_BUILD environment variable") - -TEMPLATE = aux - -STATIC_BASE = $$PWD -STATIC_DIRS = templates - -for(data_dir, STATIC_DIRS) { - files = $$files($$STATIC_BASE/$$data_dir/*, true) - for(file, files): !exists($$file/*): STATIC_FILES += $$file -} - -include($$IDE_SOURCE_TREE/share/qtcreator/static.pri) - diff --git a/plugins/autotest/AutoTest.json.in b/src/plugins/autotest/AutoTest.json.in similarity index 100% rename from plugins/autotest/AutoTest.json.in rename to src/plugins/autotest/AutoTest.json.in diff --git a/plugins/autotest/autotest.pro b/src/plugins/autotest/autotest.pro similarity index 100% rename from plugins/autotest/autotest.pro rename to src/plugins/autotest/autotest.pro diff --git a/plugins/autotest/autotest.qbs b/src/plugins/autotest/autotest.qbs similarity index 100% rename from plugins/autotest/autotest.qbs rename to src/plugins/autotest/autotest.qbs diff --git a/plugins/autotest/autotest.qrc b/src/plugins/autotest/autotest.qrc similarity index 100% rename from plugins/autotest/autotest.qrc rename to src/plugins/autotest/autotest.qrc diff --git a/plugins/autotest/autotest_dependencies.pri b/src/plugins/autotest/autotest_dependencies.pri similarity index 100% rename from plugins/autotest/autotest_dependencies.pri rename to src/plugins/autotest/autotest_dependencies.pri diff --git a/plugins/autotest/autotest_global.h b/src/plugins/autotest/autotest_global.h similarity index 100% rename from plugins/autotest/autotest_global.h rename to src/plugins/autotest/autotest_global.h diff --git a/plugins/autotest/autotest_utils.h b/src/plugins/autotest/autotest_utils.h similarity index 100% rename from plugins/autotest/autotest_utils.h rename to src/plugins/autotest/autotest_utils.h diff --git a/plugins/autotest/autotestconstants.h b/src/plugins/autotest/autotestconstants.h similarity index 100% rename from plugins/autotest/autotestconstants.h rename to src/plugins/autotest/autotestconstants.h diff --git a/plugins/autotest/autotesticons.h b/src/plugins/autotest/autotesticons.h similarity index 100% rename from plugins/autotest/autotesticons.h rename to src/plugins/autotest/autotesticons.h diff --git a/plugins/autotest/autotestplugin.cpp b/src/plugins/autotest/autotestplugin.cpp similarity index 100% rename from plugins/autotest/autotestplugin.cpp rename to src/plugins/autotest/autotestplugin.cpp diff --git a/plugins/autotest/autotestplugin.h b/src/plugins/autotest/autotestplugin.h similarity index 100% rename from plugins/autotest/autotestplugin.h rename to src/plugins/autotest/autotestplugin.h diff --git a/plugins/autotest/autotestunittests.cpp b/src/plugins/autotest/autotestunittests.cpp similarity index 100% rename from plugins/autotest/autotestunittests.cpp rename to src/plugins/autotest/autotestunittests.cpp diff --git a/plugins/autotest/autotestunittests.h b/src/plugins/autotest/autotestunittests.h similarity index 100% rename from plugins/autotest/autotestunittests.h rename to src/plugins/autotest/autotestunittests.h diff --git a/plugins/autotest/autotestunittests.qrc b/src/plugins/autotest/autotestunittests.qrc similarity index 100% rename from plugins/autotest/autotestunittests.qrc rename to src/plugins/autotest/autotestunittests.qrc diff --git a/plugins/autotest/images/autotest.png b/src/plugins/autotest/images/autotest.png similarity index 100% rename from plugins/autotest/images/autotest.png rename to src/plugins/autotest/images/autotest.png diff --git a/plugins/autotest/images/benchmark.png b/src/plugins/autotest/images/benchmark.png similarity index 100% rename from plugins/autotest/images/benchmark.png rename to src/plugins/autotest/images/benchmark.png diff --git a/plugins/autotest/images/blacklisted_fail.png b/src/plugins/autotest/images/blacklisted_fail.png similarity index 100% rename from plugins/autotest/images/blacklisted_fail.png rename to src/plugins/autotest/images/blacklisted_fail.png diff --git a/plugins/autotest/images/blacklisted_pass.png b/src/plugins/autotest/images/blacklisted_pass.png similarity index 100% rename from plugins/autotest/images/blacklisted_pass.png rename to src/plugins/autotest/images/blacklisted_pass.png diff --git a/plugins/autotest/images/class.png b/src/plugins/autotest/images/class.png similarity index 100% rename from plugins/autotest/images/class.png rename to src/plugins/autotest/images/class.png diff --git a/plugins/autotest/images/collapse.png b/src/plugins/autotest/images/collapse.png similarity index 100% rename from plugins/autotest/images/collapse.png rename to src/plugins/autotest/images/collapse.png diff --git a/plugins/autotest/images/collapse@2x.png b/src/plugins/autotest/images/collapse@2x.png similarity index 100% rename from plugins/autotest/images/collapse@2x.png rename to src/plugins/autotest/images/collapse@2x.png diff --git a/plugins/autotest/images/data.png b/src/plugins/autotest/images/data.png similarity index 100% rename from plugins/autotest/images/data.png rename to src/plugins/autotest/images/data.png diff --git a/plugins/autotest/images/debug.png b/src/plugins/autotest/images/debug.png similarity index 100% rename from plugins/autotest/images/debug.png rename to src/plugins/autotest/images/debug.png diff --git a/plugins/autotest/images/expand.png b/src/plugins/autotest/images/expand.png similarity index 100% rename from plugins/autotest/images/expand.png rename to src/plugins/autotest/images/expand.png diff --git a/plugins/autotest/images/expand@2x.png b/src/plugins/autotest/images/expand@2x.png similarity index 100% rename from plugins/autotest/images/expand@2x.png rename to src/plugins/autotest/images/expand@2x.png diff --git a/plugins/autotest/images/fail.png b/src/plugins/autotest/images/fail.png similarity index 100% rename from plugins/autotest/images/fail.png rename to src/plugins/autotest/images/fail.png diff --git a/plugins/autotest/images/fatal.png b/src/plugins/autotest/images/fatal.png similarity index 100% rename from plugins/autotest/images/fatal.png rename to src/plugins/autotest/images/fatal.png diff --git a/plugins/autotest/images/func.png b/src/plugins/autotest/images/func.png similarity index 100% rename from plugins/autotest/images/func.png rename to src/plugins/autotest/images/func.png diff --git a/plugins/autotest/images/leafsort.png b/src/plugins/autotest/images/leafsort.png similarity index 100% rename from plugins/autotest/images/leafsort.png rename to src/plugins/autotest/images/leafsort.png diff --git a/plugins/autotest/images/leafsort@2x.png b/src/plugins/autotest/images/leafsort@2x.png similarity index 100% rename from plugins/autotest/images/leafsort@2x.png rename to src/plugins/autotest/images/leafsort@2x.png diff --git a/plugins/autotest/images/pass.png b/src/plugins/autotest/images/pass.png similarity index 100% rename from plugins/autotest/images/pass.png rename to src/plugins/autotest/images/pass.png diff --git a/plugins/autotest/images/runselected_boxes.png b/src/plugins/autotest/images/runselected_boxes.png similarity index 100% rename from plugins/autotest/images/runselected_boxes.png rename to src/plugins/autotest/images/runselected_boxes.png diff --git a/plugins/autotest/images/runselected_boxes@2x.png b/src/plugins/autotest/images/runselected_boxes@2x.png similarity index 100% rename from plugins/autotest/images/runselected_boxes@2x.png rename to src/plugins/autotest/images/runselected_boxes@2x.png diff --git a/plugins/autotest/images/runselected_tickmarks.png b/src/plugins/autotest/images/runselected_tickmarks.png similarity index 100% rename from plugins/autotest/images/runselected_tickmarks.png rename to src/plugins/autotest/images/runselected_tickmarks.png diff --git a/plugins/autotest/images/runselected_tickmarks@2x.png b/src/plugins/autotest/images/runselected_tickmarks@2x.png similarity index 100% rename from plugins/autotest/images/runselected_tickmarks@2x.png rename to src/plugins/autotest/images/runselected_tickmarks@2x.png diff --git a/plugins/autotest/images/skip.png b/src/plugins/autotest/images/skip.png similarity index 100% rename from plugins/autotest/images/skip.png rename to src/plugins/autotest/images/skip.png diff --git a/plugins/autotest/images/sort.png b/src/plugins/autotest/images/sort.png similarity index 100% rename from plugins/autotest/images/sort.png rename to src/plugins/autotest/images/sort.png diff --git a/plugins/autotest/images/sort@2x.png b/src/plugins/autotest/images/sort@2x.png similarity index 100% rename from plugins/autotest/images/sort@2x.png rename to src/plugins/autotest/images/sort@2x.png diff --git a/plugins/autotest/images/warn.png b/src/plugins/autotest/images/warn.png similarity index 100% rename from plugins/autotest/images/warn.png rename to src/plugins/autotest/images/warn.png diff --git a/plugins/autotest/images/xfail.png b/src/plugins/autotest/images/xfail.png similarity index 100% rename from plugins/autotest/images/xfail.png rename to src/plugins/autotest/images/xfail.png diff --git a/plugins/autotest/images/xpass.png b/src/plugins/autotest/images/xpass.png similarity index 100% rename from plugins/autotest/images/xpass.png rename to src/plugins/autotest/images/xpass.png diff --git a/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp similarity index 100% rename from plugins/autotest/testcodeparser.cpp rename to src/plugins/autotest/testcodeparser.cpp diff --git a/plugins/autotest/testcodeparser.h b/src/plugins/autotest/testcodeparser.h similarity index 100% rename from plugins/autotest/testcodeparser.h rename to src/plugins/autotest/testcodeparser.h diff --git a/plugins/autotest/testconfiguration.cpp b/src/plugins/autotest/testconfiguration.cpp similarity index 100% rename from plugins/autotest/testconfiguration.cpp rename to src/plugins/autotest/testconfiguration.cpp diff --git a/plugins/autotest/testconfiguration.h b/src/plugins/autotest/testconfiguration.h similarity index 100% rename from plugins/autotest/testconfiguration.h rename to src/plugins/autotest/testconfiguration.h diff --git a/plugins/autotest/testinfo.cpp b/src/plugins/autotest/testinfo.cpp similarity index 100% rename from plugins/autotest/testinfo.cpp rename to src/plugins/autotest/testinfo.cpp diff --git a/plugins/autotest/testinfo.h b/src/plugins/autotest/testinfo.h similarity index 100% rename from plugins/autotest/testinfo.h rename to src/plugins/autotest/testinfo.h diff --git a/plugins/autotest/testnavigationwidget.cpp b/src/plugins/autotest/testnavigationwidget.cpp similarity index 100% rename from plugins/autotest/testnavigationwidget.cpp rename to src/plugins/autotest/testnavigationwidget.cpp diff --git a/plugins/autotest/testnavigationwidget.h b/src/plugins/autotest/testnavigationwidget.h similarity index 100% rename from plugins/autotest/testnavigationwidget.h rename to src/plugins/autotest/testnavigationwidget.h diff --git a/plugins/autotest/testoutputreader.cpp b/src/plugins/autotest/testoutputreader.cpp similarity index 100% rename from plugins/autotest/testoutputreader.cpp rename to src/plugins/autotest/testoutputreader.cpp diff --git a/plugins/autotest/testoutputreader.h b/src/plugins/autotest/testoutputreader.h similarity index 100% rename from plugins/autotest/testoutputreader.h rename to src/plugins/autotest/testoutputreader.h diff --git a/plugins/autotest/testresult.cpp b/src/plugins/autotest/testresult.cpp similarity index 100% rename from plugins/autotest/testresult.cpp rename to src/plugins/autotest/testresult.cpp diff --git a/plugins/autotest/testresult.h b/src/plugins/autotest/testresult.h similarity index 100% rename from plugins/autotest/testresult.h rename to src/plugins/autotest/testresult.h diff --git a/plugins/autotest/testresultdelegate.cpp b/src/plugins/autotest/testresultdelegate.cpp similarity index 100% rename from plugins/autotest/testresultdelegate.cpp rename to src/plugins/autotest/testresultdelegate.cpp diff --git a/plugins/autotest/testresultdelegate.h b/src/plugins/autotest/testresultdelegate.h similarity index 100% rename from plugins/autotest/testresultdelegate.h rename to src/plugins/autotest/testresultdelegate.h diff --git a/plugins/autotest/testresultmodel.cpp b/src/plugins/autotest/testresultmodel.cpp similarity index 100% rename from plugins/autotest/testresultmodel.cpp rename to src/plugins/autotest/testresultmodel.cpp diff --git a/plugins/autotest/testresultmodel.h b/src/plugins/autotest/testresultmodel.h similarity index 100% rename from plugins/autotest/testresultmodel.h rename to src/plugins/autotest/testresultmodel.h diff --git a/plugins/autotest/testresultspane.cpp b/src/plugins/autotest/testresultspane.cpp similarity index 100% rename from plugins/autotest/testresultspane.cpp rename to src/plugins/autotest/testresultspane.cpp diff --git a/plugins/autotest/testresultspane.h b/src/plugins/autotest/testresultspane.h similarity index 100% rename from plugins/autotest/testresultspane.h rename to src/plugins/autotest/testresultspane.h diff --git a/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp similarity index 100% rename from plugins/autotest/testrunner.cpp rename to src/plugins/autotest/testrunner.cpp diff --git a/plugins/autotest/testrunner.h b/src/plugins/autotest/testrunner.h similarity index 100% rename from plugins/autotest/testrunner.h rename to src/plugins/autotest/testrunner.h diff --git a/plugins/autotest/testsettings.cpp b/src/plugins/autotest/testsettings.cpp similarity index 100% rename from plugins/autotest/testsettings.cpp rename to src/plugins/autotest/testsettings.cpp diff --git a/plugins/autotest/testsettings.h b/src/plugins/autotest/testsettings.h similarity index 100% rename from plugins/autotest/testsettings.h rename to src/plugins/autotest/testsettings.h diff --git a/plugins/autotest/testsettingspage.cpp b/src/plugins/autotest/testsettingspage.cpp similarity index 100% rename from plugins/autotest/testsettingspage.cpp rename to src/plugins/autotest/testsettingspage.cpp diff --git a/plugins/autotest/testsettingspage.h b/src/plugins/autotest/testsettingspage.h similarity index 100% rename from plugins/autotest/testsettingspage.h rename to src/plugins/autotest/testsettingspage.h diff --git a/plugins/autotest/testsettingspage.ui b/src/plugins/autotest/testsettingspage.ui similarity index 100% rename from plugins/autotest/testsettingspage.ui rename to src/plugins/autotest/testsettingspage.ui diff --git a/plugins/autotest/testtreeitem.cpp b/src/plugins/autotest/testtreeitem.cpp similarity index 100% rename from plugins/autotest/testtreeitem.cpp rename to src/plugins/autotest/testtreeitem.cpp diff --git a/plugins/autotest/testtreeitem.h b/src/plugins/autotest/testtreeitem.h similarity index 100% rename from plugins/autotest/testtreeitem.h rename to src/plugins/autotest/testtreeitem.h diff --git a/plugins/autotest/testtreeitemdelegate.cpp b/src/plugins/autotest/testtreeitemdelegate.cpp similarity index 100% rename from plugins/autotest/testtreeitemdelegate.cpp rename to src/plugins/autotest/testtreeitemdelegate.cpp diff --git a/plugins/autotest/testtreeitemdelegate.h b/src/plugins/autotest/testtreeitemdelegate.h similarity index 100% rename from plugins/autotest/testtreeitemdelegate.h rename to src/plugins/autotest/testtreeitemdelegate.h diff --git a/plugins/autotest/testtreemodel.cpp b/src/plugins/autotest/testtreemodel.cpp similarity index 100% rename from plugins/autotest/testtreemodel.cpp rename to src/plugins/autotest/testtreemodel.cpp diff --git a/plugins/autotest/testtreemodel.h b/src/plugins/autotest/testtreemodel.h similarity index 100% rename from plugins/autotest/testtreemodel.h rename to src/plugins/autotest/testtreemodel.h diff --git a/plugins/autotest/testtreeview.cpp b/src/plugins/autotest/testtreeview.cpp similarity index 100% rename from plugins/autotest/testtreeview.cpp rename to src/plugins/autotest/testtreeview.cpp diff --git a/plugins/autotest/testtreeview.h b/src/plugins/autotest/testtreeview.h similarity index 100% rename from plugins/autotest/testtreeview.h rename to src/plugins/autotest/testtreeview.h diff --git a/plugins/autotest/testvisitor.cpp b/src/plugins/autotest/testvisitor.cpp similarity index 100% rename from plugins/autotest/testvisitor.cpp rename to src/plugins/autotest/testvisitor.cpp diff --git a/plugins/autotest/testvisitor.h b/src/plugins/autotest/testvisitor.h similarity index 100% rename from plugins/autotest/testvisitor.h rename to src/plugins/autotest/testvisitor.h diff --git a/plugins/autotest/unit_test/mixed_atp/mixed_atp.pro b/src/plugins/autotest/unit_test/mixed_atp/mixed_atp.pro similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/mixed_atp.pro rename to src/plugins/autotest/unit_test/mixed_atp/mixed_atp.pro diff --git a/plugins/autotest/unit_test/mixed_atp/mixed_atp.qbs b/src/plugins/autotest/unit_test/mixed_atp/mixed_atp.qbs similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/mixed_atp.qbs rename to src/plugins/autotest/unit_test/mixed_atp/mixed_atp.qbs diff --git a/plugins/autotest/unit_test/mixed_atp/src/main.cpp b/src/plugins/autotest/unit_test/mixed_atp/src/main.cpp similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/src/main.cpp rename to src/plugins/autotest/unit_test/mixed_atp/src/main.cpp diff --git a/plugins/autotest/unit_test/mixed_atp/src/src.pro b/src/plugins/autotest/unit_test/mixed_atp/src/src.pro similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/src/src.pro rename to src/plugins/autotest/unit_test/mixed_atp/src/src.pro diff --git a/plugins/autotest/unit_test/mixed_atp/src/src.qbs b/src/plugins/autotest/unit_test/mixed_atp/src/src.qbs similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/src/src.qbs rename to src/plugins/autotest/unit_test/mixed_atp/src/src.qbs diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/auto.pro b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/auto.pro similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/auto.pro rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/auto.pro diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/auto.qbs b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/auto.qbs similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/auto.qbs rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/auto.qbs diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.pro b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.pro similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.pro rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.pro diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.qbs b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.qbs similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.qbs rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.qbs diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/tst_benchtest.cpp diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.pro b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.pro similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.pro rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.pro diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.qbs b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.qbs similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.qbs rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.qbs diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.cpp diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/tst_foo.h diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.pro b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.pro similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.pro rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.pro diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.qbs b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.qbs similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.qbs rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.qbs diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/tst_guitest.cpp diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/TestDummy.qml b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/TestDummy.qml similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/TestDummy.qml rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/TestDummy.qml diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/bar/tst_foo.qml diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/main.cpp b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/main.cpp similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/main.cpp rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/main.cpp diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/notlisted/tst_bla.qml diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.pro b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.pro similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.pro rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.pro diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.qbs b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.qbs similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.qbs rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.qbs diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test1.qml diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test2.qml diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/tst_test3.qml diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/main.cpp b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/main.cpp similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/main.cpp rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/main.cpp diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.pro b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.pro similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.pro rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.pro diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test1.qml diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml b/src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml rename to src/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/tst_test2.qml diff --git a/plugins/autotest/unit_test/mixed_atp/tests/tests.pro b/src/plugins/autotest/unit_test/mixed_atp/tests/tests.pro similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/tests.pro rename to src/plugins/autotest/unit_test/mixed_atp/tests/tests.pro diff --git a/plugins/autotest/unit_test/mixed_atp/tests/tests.qbs b/src/plugins/autotest/unit_test/mixed_atp/tests/tests.qbs similarity index 100% rename from plugins/autotest/unit_test/mixed_atp/tests/tests.qbs rename to src/plugins/autotest/unit_test/mixed_atp/tests/tests.qbs diff --git a/plugins/autotest/unit_test/plain/plain.pro b/src/plugins/autotest/unit_test/plain/plain.pro similarity index 100% rename from plugins/autotest/unit_test/plain/plain.pro rename to src/plugins/autotest/unit_test/plain/plain.pro diff --git a/plugins/autotest/unit_test/plain/plain.qbs b/src/plugins/autotest/unit_test/plain/plain.qbs similarity index 100% rename from plugins/autotest/unit_test/plain/plain.qbs rename to src/plugins/autotest/unit_test/plain/plain.qbs diff --git a/plugins/autotest/unit_test/plain/test_plain/test_plain.pro b/src/plugins/autotest/unit_test/plain/test_plain/test_plain.pro similarity index 100% rename from plugins/autotest/unit_test/plain/test_plain/test_plain.pro rename to src/plugins/autotest/unit_test/plain/test_plain/test_plain.pro diff --git a/plugins/autotest/unit_test/plain/test_plain/test_plain.qbs b/src/plugins/autotest/unit_test/plain/test_plain/test_plain.qbs similarity index 100% rename from plugins/autotest/unit_test/plain/test_plain/test_plain.qbs rename to src/plugins/autotest/unit_test/plain/test_plain/test_plain.qbs diff --git a/plugins/autotest/unit_test/plain/test_plain/tst_simple.cpp b/src/plugins/autotest/unit_test/plain/test_plain/tst_simple.cpp similarity index 100% rename from plugins/autotest/unit_test/plain/test_plain/tst_simple.cpp rename to src/plugins/autotest/unit_test/plain/test_plain/tst_simple.cpp diff --git a/plugins/autotest/unit_test/plain/test_plain/tst_simple.h b/src/plugins/autotest/unit_test/plain/test_plain/tst_simple.h similarity index 100% rename from plugins/autotest/unit_test/plain/test_plain/tst_simple.h rename to src/plugins/autotest/unit_test/plain/test_plain/tst_simple.h diff --git a/plugins/autotest/unit_test/simple_gt/simple_gt.pro b/src/plugins/autotest/unit_test/simple_gt/simple_gt.pro similarity index 100% rename from plugins/autotest/unit_test/simple_gt/simple_gt.pro rename to src/plugins/autotest/unit_test/simple_gt/simple_gt.pro diff --git a/plugins/autotest/unit_test/simple_gt/src/main.cpp b/src/plugins/autotest/unit_test/simple_gt/src/main.cpp similarity index 100% rename from plugins/autotest/unit_test/simple_gt/src/main.cpp rename to src/plugins/autotest/unit_test/simple_gt/src/main.cpp diff --git a/plugins/autotest/unit_test/simple_gt/src/src.pro b/src/plugins/autotest/unit_test/simple_gt/src/src.pro similarity index 100% rename from plugins/autotest/unit_test/simple_gt/src/src.pro rename to src/plugins/autotest/unit_test/simple_gt/src/src.pro diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt1/further.cpp b/src/plugins/autotest/unit_test/simple_gt/tests/gt1/further.cpp similarity index 100% rename from plugins/autotest/unit_test/simple_gt/tests/gt1/further.cpp rename to src/plugins/autotest/unit_test/simple_gt/tests/gt1/further.cpp diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt1/gt1.pro b/src/plugins/autotest/unit_test/simple_gt/tests/gt1/gt1.pro similarity index 100% rename from plugins/autotest/unit_test/simple_gt/tests/gt1/gt1.pro rename to src/plugins/autotest/unit_test/simple_gt/tests/gt1/gt1.pro diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt1/main.cpp b/src/plugins/autotest/unit_test/simple_gt/tests/gt1/main.cpp similarity index 100% rename from plugins/autotest/unit_test/simple_gt/tests/gt1/main.cpp rename to src/plugins/autotest/unit_test/simple_gt/tests/gt1/main.cpp diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt2/gt2.pro b/src/plugins/autotest/unit_test/simple_gt/tests/gt2/gt2.pro similarity index 100% rename from plugins/autotest/unit_test/simple_gt/tests/gt2/gt2.pro rename to src/plugins/autotest/unit_test/simple_gt/tests/gt2/gt2.pro diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt2/main.cpp b/src/plugins/autotest/unit_test/simple_gt/tests/gt2/main.cpp similarity index 100% rename from plugins/autotest/unit_test/simple_gt/tests/gt2/main.cpp rename to src/plugins/autotest/unit_test/simple_gt/tests/gt2/main.cpp diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h b/src/plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h similarity index 100% rename from plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h rename to src/plugins/autotest/unit_test/simple_gt/tests/gt2/queuetest.h diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt3/dummytest.h b/src/plugins/autotest/unit_test/simple_gt/tests/gt3/dummytest.h similarity index 100% rename from plugins/autotest/unit_test/simple_gt/tests/gt3/dummytest.h rename to src/plugins/autotest/unit_test/simple_gt/tests/gt3/dummytest.h diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt3/gt3.pro b/src/plugins/autotest/unit_test/simple_gt/tests/gt3/gt3.pro similarity index 100% rename from plugins/autotest/unit_test/simple_gt/tests/gt3/gt3.pro rename to src/plugins/autotest/unit_test/simple_gt/tests/gt3/gt3.pro diff --git a/plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp b/src/plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp similarity index 100% rename from plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp rename to src/plugins/autotest/unit_test/simple_gt/tests/gt3/main.cpp diff --git a/plugins/autotest/unit_test/simple_gt/tests/gtest_dependency.pri b/src/plugins/autotest/unit_test/simple_gt/tests/gtest_dependency.pri similarity index 100% rename from plugins/autotest/unit_test/simple_gt/tests/gtest_dependency.pri rename to src/plugins/autotest/unit_test/simple_gt/tests/gtest_dependency.pri diff --git a/plugins/autotest/unit_test/simple_gt/tests/tests.pro b/src/plugins/autotest/unit_test/simple_gt/tests/tests.pro similarity index 100% rename from plugins/autotest/unit_test/simple_gt/tests/tests.pro rename to src/plugins/autotest/unit_test/simple_gt/tests/tests.pro From a73871d91c0ff29fb8c239be31e8cba3c6ba83f1 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Fri, 22 Jan 2016 15:16:01 +0100 Subject: [PATCH 200/200] Fix wrong location of templates Change-Id: Id7732ef0914ba69eae020feb412cbce7cf9a5902 Reviewed-by: Eike Ziller --- .../qtcreator/templates/wizards/autotest/auto.pro | 0 .../templates/wizards/autotest/autotest_24.png | Bin .../qtcreator/templates/wizards/autotest/main.cpp | 0 .../qtcreator/templates/wizards/autotest/src.pro | 0 .../qtcreator/templates/wizards/autotest/tests.pro | 0 .../qtcreator/templates/wizards/autotest/tmp.pro | 0 .../qtcreator/templates/wizards/autotest/tst.pro | 0 .../templates/wizards/autotest/tst_src.cpp | 0 .../qtcreator/templates/wizards/autotest/wizard.xml | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename {shared => share}/qtcreator/templates/wizards/autotest/auto.pro (100%) rename {shared => share}/qtcreator/templates/wizards/autotest/autotest_24.png (100%) rename {shared => share}/qtcreator/templates/wizards/autotest/main.cpp (100%) rename {shared => share}/qtcreator/templates/wizards/autotest/src.pro (100%) rename {shared => share}/qtcreator/templates/wizards/autotest/tests.pro (100%) rename {shared => share}/qtcreator/templates/wizards/autotest/tmp.pro (100%) rename {shared => share}/qtcreator/templates/wizards/autotest/tst.pro (100%) rename {shared => share}/qtcreator/templates/wizards/autotest/tst_src.cpp (100%) rename {shared => share}/qtcreator/templates/wizards/autotest/wizard.xml (100%) diff --git a/shared/qtcreator/templates/wizards/autotest/auto.pro b/share/qtcreator/templates/wizards/autotest/auto.pro similarity index 100% rename from shared/qtcreator/templates/wizards/autotest/auto.pro rename to share/qtcreator/templates/wizards/autotest/auto.pro diff --git a/shared/qtcreator/templates/wizards/autotest/autotest_24.png b/share/qtcreator/templates/wizards/autotest/autotest_24.png similarity index 100% rename from shared/qtcreator/templates/wizards/autotest/autotest_24.png rename to share/qtcreator/templates/wizards/autotest/autotest_24.png diff --git a/shared/qtcreator/templates/wizards/autotest/main.cpp b/share/qtcreator/templates/wizards/autotest/main.cpp similarity index 100% rename from shared/qtcreator/templates/wizards/autotest/main.cpp rename to share/qtcreator/templates/wizards/autotest/main.cpp diff --git a/shared/qtcreator/templates/wizards/autotest/src.pro b/share/qtcreator/templates/wizards/autotest/src.pro similarity index 100% rename from shared/qtcreator/templates/wizards/autotest/src.pro rename to share/qtcreator/templates/wizards/autotest/src.pro diff --git a/shared/qtcreator/templates/wizards/autotest/tests.pro b/share/qtcreator/templates/wizards/autotest/tests.pro similarity index 100% rename from shared/qtcreator/templates/wizards/autotest/tests.pro rename to share/qtcreator/templates/wizards/autotest/tests.pro diff --git a/shared/qtcreator/templates/wizards/autotest/tmp.pro b/share/qtcreator/templates/wizards/autotest/tmp.pro similarity index 100% rename from shared/qtcreator/templates/wizards/autotest/tmp.pro rename to share/qtcreator/templates/wizards/autotest/tmp.pro diff --git a/shared/qtcreator/templates/wizards/autotest/tst.pro b/share/qtcreator/templates/wizards/autotest/tst.pro similarity index 100% rename from shared/qtcreator/templates/wizards/autotest/tst.pro rename to share/qtcreator/templates/wizards/autotest/tst.pro diff --git a/shared/qtcreator/templates/wizards/autotest/tst_src.cpp b/share/qtcreator/templates/wizards/autotest/tst_src.cpp similarity index 100% rename from shared/qtcreator/templates/wizards/autotest/tst_src.cpp rename to share/qtcreator/templates/wizards/autotest/tst_src.cpp diff --git a/shared/qtcreator/templates/wizards/autotest/wizard.xml b/share/qtcreator/templates/wizards/autotest/wizard.xml similarity index 100% rename from shared/qtcreator/templates/wizards/autotest/wizard.xml rename to share/qtcreator/templates/wizards/autotest/wizard.xml