File indexing completed on 2024-05-19 04:42:05
0001 /* 0002 SPDX-FileCopyrightText: 2010 Benjamin Port <port.benjamin@gmail.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "test_qthelpplugin.h" 0008 #include "../qthelpplugin.h" 0009 #include "../qthelpprovider.h" 0010 #include "../qthelp_config_shared.h" 0011 0012 #include <QCoreApplication> 0013 #include <QTest> 0014 #include <QHelpLink> 0015 0016 #include <interfaces/idocumentation.h> 0017 #include <language/duchain/duchainlock.h> 0018 #include <language/duchain/declaration.h> 0019 #include <language/duchain/types/identifiedtype.h> 0020 #include <language/duchain/types/pointertype.h> 0021 #include <tests/autotestshell.h> 0022 #include <tests/testfile.h> 0023 0024 #include "testqthelpconfig.h" 0025 0026 const QString VALID1 = QTHELP_FILES "/valid1.qch"; 0027 const QString VALID2 = QTHELP_FILES "/valid2.qch"; 0028 const QString INVALID = QTHELP_FILES "/invalid.qch"; 0029 0030 QTEST_MAIN(TestQtHelpPlugin) 0031 using namespace KDevelop; 0032 0033 TestQtHelpPlugin::TestQtHelpPlugin() 0034 : m_testCore(nullptr) 0035 , m_plugin(nullptr) 0036 { 0037 } 0038 0039 void TestQtHelpPlugin::initTestCase() 0040 { 0041 AutoTestShell::init({"kdevqthelp"}); 0042 0043 // Prevent SegFault, then "ICE default IO error handler doing an exit(), pid = <PID>, errno = 32" 0044 // crash when the test runs for at least 60 seconds. This is a workaround for QTBUG-58709. 0045 QCoreApplication::processEvents(); 0046 0047 m_testCore = new TestCore(); 0048 m_testCore->initialize(); 0049 } 0050 0051 void TestQtHelpPlugin::init() 0052 { 0053 m_plugin = new QtHelpPlugin(m_testCore, QVariantList()); 0054 // write default config and read it 0055 qtHelpWriteConfig(QStringList(), QStringList(), QStringList(), QStringList(), QString(), true); 0056 m_plugin->readConfig(); 0057 QTRY_VERIFY(m_plugin->isQtHelpQtDocLoaded()); 0058 } 0059 0060 void TestQtHelpPlugin::cleanup() 0061 { 0062 delete m_plugin; 0063 } 0064 0065 void TestQtHelpPlugin::cleanupTestCase() 0066 { 0067 m_testCore->cleanup(); 0068 delete m_testCore; 0069 } 0070 0071 void TestQtHelpPlugin::testDefaultValue() 0072 { 0073 QCOMPARE(m_plugin->isQtHelpQtDocLoaded(), true); 0074 QCOMPARE(m_plugin->qtHelpProviderLoaded().size(), 0); 0075 QCOMPARE(m_plugin->providers().size(), 1); 0076 } 0077 0078 void TestQtHelpPlugin::testUnsetQtHelpDoc() 0079 { 0080 qtHelpWriteConfig(QStringList(), QStringList(), QStringList(), QStringList(), QString(), false); 0081 m_plugin->readConfig(); 0082 0083 QCOMPARE(m_plugin->providers().size(), 0); 0084 } 0085 0086 void TestQtHelpPlugin::testAddOneValidProvider() 0087 { 0088 QStringList path, name, icon, ghns; 0089 path << VALID1; 0090 name << QStringLiteral("file1"); 0091 icon << QStringLiteral("myIcon"); 0092 ghns << QStringLiteral("0"); 0093 qtHelpWriteConfig(icon, name, path, ghns, QString(), true); 0094 m_plugin->readConfig(); 0095 0096 QCOMPARE(m_plugin->qtHelpProviderLoaded().size(), 1); 0097 QCOMPARE(m_plugin->qtHelpProviderLoaded().at(0)->fileName(), path.at(0)); 0098 QCOMPARE(m_plugin->qtHelpProviderLoaded().at(0)->name(), name.at(0)); 0099 QCOMPARE(m_plugin->qtHelpProviderLoaded().at(0)->iconName(), icon.at(0)); 0100 } 0101 0102 void TestQtHelpPlugin::testAddTwoDifferentValidProvider() 0103 { 0104 QStringList path, name, icon, ghns; 0105 path << VALID1 << VALID2; 0106 name << QStringLiteral("file1") << QStringLiteral("file2"); 0107 icon << QStringLiteral("myIcon") << QStringLiteral("myIcon"); 0108 ghns << QStringLiteral("0") << QStringLiteral("0"); 0109 qtHelpWriteConfig(icon, name, path, ghns, QString(), true); 0110 m_plugin->readConfig(); 0111 0112 QCOMPARE(m_plugin->qtHelpProviderLoaded().size(), 2); 0113 // first provider 0114 QCOMPARE(m_plugin->qtHelpProviderLoaded().at(0)->fileName(), path.at(0)); 0115 QCOMPARE(m_plugin->qtHelpProviderLoaded().at(0)->name(), name.at(0)); 0116 QCOMPARE(m_plugin->qtHelpProviderLoaded().at(0)->iconName(), icon.at(0)); 0117 // second provider 0118 QCOMPARE(m_plugin->qtHelpProviderLoaded().at(1)->fileName(), path.at(1)); 0119 QCOMPARE(m_plugin->qtHelpProviderLoaded().at(1)->name(), name.at(1)); 0120 QCOMPARE(m_plugin->qtHelpProviderLoaded().at(1)->iconName(), icon.at(1)); 0121 } 0122 0123 void TestQtHelpPlugin::testAddInvalidProvider() 0124 { 0125 QStringList path, name, icon, ghns; 0126 path << INVALID; 0127 name << QStringLiteral("file1"); 0128 icon << QStringLiteral("myIcon"); 0129 ghns << QStringLiteral("0"); 0130 qtHelpWriteConfig(icon, name, path, ghns, QString(), true); 0131 m_plugin->readConfig(); 0132 0133 QCOMPARE(m_plugin->qtHelpProviderLoaded().size(), 0); 0134 } 0135 0136 void TestQtHelpPlugin::testAddTwiceSameProvider() 0137 { 0138 QStringList path, name, icon, ghns; 0139 path << VALID1 << VALID1; 0140 name << QStringLiteral("file1") << QStringLiteral("file2"); 0141 icon << QStringLiteral("myIcon") << QStringLiteral("myIcon"); 0142 ghns << QStringLiteral("0") << QStringLiteral("0"); 0143 qtHelpWriteConfig(icon, name, path, ghns, QString(), true); 0144 m_plugin->readConfig(); 0145 0146 QCOMPARE(m_plugin->qtHelpProviderLoaded().size(), 1); 0147 } 0148 0149 void TestQtHelpPlugin::testRemoveOneProvider() 0150 { 0151 QStringList path, name, icon, ghns; 0152 path << VALID1 << VALID2; 0153 name << QStringLiteral("file1") << QStringLiteral("file2"); 0154 icon << QStringLiteral("myIcon") << QStringLiteral("myIcon"); 0155 ghns << QStringLiteral("0") << QStringLiteral("0"); 0156 qtHelpWriteConfig(icon, name, path, ghns, QString(), true); 0157 m_plugin->readConfig(); 0158 0159 QCOMPARE(m_plugin->qtHelpProviderLoaded().size(), 2); 0160 // we remove the second provider 0161 QtHelpProvider *provider = m_plugin->qtHelpProviderLoaded().at(0); 0162 path.removeAt(1); 0163 name.removeAt(1); 0164 icon.removeAt(1); 0165 ghns.removeAt(1); 0166 qtHelpWriteConfig(icon, name, path, ghns, QString(), true); 0167 m_plugin->readConfig(); 0168 0169 QCOMPARE(m_plugin->qtHelpProviderLoaded().size(), 1); 0170 QCOMPARE(m_plugin->qtHelpProviderLoaded().at(0), provider); 0171 } 0172 0173 void TestQtHelpPlugin::testDeclarationLookup_Class() 0174 { 0175 init(); 0176 0177 TestFile file(QStringLiteral("class QObject; QObject* o;"), QStringLiteral("cpp")); 0178 QVERIFY(file.parseAndWait()); 0179 0180 DUChainReadLocker lock; 0181 auto ctx = file.topContext(); 0182 QVERIFY(ctx); 0183 auto decl = ctx->findDeclarations(QualifiedIdentifier(QStringLiteral("o"))).first(); 0184 QVERIFY(decl); 0185 auto typeDecl = dynamic_cast<const IdentifiedType*>(decl->type<PointerType>()->baseType().data())->declaration(nullptr); 0186 QVERIFY(typeDecl); 0187 0188 auto provider = dynamic_cast<QtHelpProviderAbstract*>(m_plugin->providers().at(0)); 0189 QVERIFY(provider); 0190 if (!provider->isValid() || provider->engine()->documentsForIdentifier(QStringLiteral("QObject")).isEmpty()) { 0191 QSKIP("Qt help not available"); 0192 } 0193 0194 auto doc = provider->documentationForDeclaration(typeDecl); 0195 QVERIFY(doc); 0196 QCOMPARE(doc->name(), QStringLiteral("QObject")); 0197 const auto description = doc->description(); 0198 QVERIFY(description.contains("QObject")); 0199 } 0200 0201 void TestQtHelpPlugin::testDeclarationLookup_Method() 0202 { 0203 init(); 0204 0205 TestFile file(QStringLiteral("class QString { static QString fromLatin1(const QByteArray&); };"), QStringLiteral("cpp")); 0206 QVERIFY(file.parseAndWait()); 0207 0208 DUChainReadLocker lock; 0209 auto ctx = file.topContext(); 0210 QVERIFY(ctx); 0211 auto decl = ctx->findDeclarations(QualifiedIdentifier(QStringLiteral("QString"))).first(); 0212 auto declFromLatin1 = decl->internalContext()->findDeclarations(QualifiedIdentifier(QStringLiteral("fromLatin1"))).first(); 0213 QVERIFY(decl); 0214 0215 auto provider = dynamic_cast<QtHelpProviderAbstract*>(m_plugin->providers().at(0)); 0216 QVERIFY(provider); 0217 if (!provider->isValid() 0218 || provider->engine()->documentsForIdentifier(QStringLiteral("QString::fromLatin1")).isEmpty()) { 0219 QSKIP("Qt help not available"); 0220 } 0221 0222 auto doc = provider->documentationForDeclaration(declFromLatin1); 0223 QVERIFY(doc); 0224 QCOMPARE(doc->name(), QStringLiteral("QString::fromLatin1")); 0225 const auto description = doc->description(); 0226 QVERIFY(description.contains("fromLatin1")); 0227 } 0228 0229 void TestQtHelpPlugin::testDeclarationLookup_OperatorFunction() 0230 { 0231 init(); 0232 0233 TestFile file(QStringLiteral("class C {}; bool operator<(const C& a, const C& b) { return true; }"), QStringLiteral("cpp")); 0234 QVERIFY(file.parseAndWait()); 0235 0236 DUChainReadLocker lock; 0237 auto ctx = file.topContext(); 0238 auto decl = ctx->findDeclarations(QualifiedIdentifier(QStringLiteral("operator<"))).first(); 0239 QVERIFY(decl); 0240 0241 auto provider = dynamic_cast<QtHelpProviderAbstract*>(m_plugin->providers().at(0)); 0242 QVERIFY(provider); 0243 if (!provider->isValid() || provider->engine()->documentsForIdentifier(QStringLiteral("QObject")).isEmpty()) { 0244 QSKIP("Qt help not available"); 0245 } 0246 0247 auto doc = provider->documentationForDeclaration(decl); 0248 // TODO: We should never find a documentation entry for this (but instead, the operator< for QChar is found here) 0249 QEXPECT_FAIL("", "doc should be null here", Continue); 0250 QVERIFY(!doc); 0251 } 0252 0253 #include "moc_test_qthelpplugin.cpp"