File indexing completed on 2024-05-12 04:38:44

0001 /*
0002     SPDX-FileCopyrightText: 2012 Olivier de Gaalon <olivier.jg@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-only
0005 */
0006 
0007 #ifndef KDEVPLATFORM_TESTSUITE_H
0008 #define KDEVPLATFORM_TESTSUITE_H
0009 
0010 #include <QVariantMap>
0011 #include "delayedoutput.h"
0012 #include <language/duchain/types/abstracttype.h>
0013 #include <QDebug>
0014 
0015 namespace KDevelop {
0016 class DUContext;
0017 
0018 class Declaration;
0019 
0020 inline QString EXPECT_FAIL()    { return QStringLiteral("EXPECT_FAIL"); }
0021 inline QString FAILED_TO_FAIL() { return QStringLiteral("\"%1\" FAILED TO FAIL AS EXPECTED: \"%2\" %3"); }
0022 inline QString EXPECTED_FAIL()  { return QStringLiteral("\"%1\" FAILED (expected): %2 %3"); }
0023 inline QString FAIL()           { return QStringLiteral("\"%1\" FAILED: %2 %3"); }
0024 inline QString TEST_NOT_FOUND() { return QStringLiteral("Test not found"); }
0025 
0026 template<class T> class TestSuite;
0027 
0028 KDEVPLATFORMTESTS_EXPORT TestSuite<KDevelop::Declaration*>& declarationTestSuite();
0029 KDEVPLATFORMTESTS_EXPORT TestSuite<KDevelop::DUContext*>& contextTestSuite();
0030 KDEVPLATFORMTESTS_EXPORT TestSuite<KDevelop::AbstractType::Ptr>& typeTestSuite();
0031 
0032 template<class T>
0033 class KDEVPLATFORMTESTS_EXPORT TestSuite
0034 {
0035 public:
0036     using TestFunction = QString (*)(const QVariant&, T);
0037     static TestSuite& get();
0038     bool addTest(const QString& testName, TestFunction testFunc)
0039     {
0040         m_testFunctions.insert(testName, testFunc);
0041         return true;
0042     }
0043     bool runTests(const QVariantMap& testData, T object)
0044     {
0045         QVariantMap expectedFails = expectedFailures(testData);
0046         QVariantMap::const_iterator it;
0047         DelayedOutput::Delay delay(&DelayedOutput::self());
0048         for (it = testData.begin(); it != testData.end(); ++it) {
0049             if (it.key() == EXPECT_FAIL())
0050                 continue;
0051 
0052             QString result = m_testFunctions.value(it.key(), &TestSuite<T>::noSuchTest)(it.value(), object);
0053             QString expectedFailure = expectedFails.value(it.key(), QString()).toString();
0054 
0055             //Either ("expected failure" & "no result failure") or ("no expected failure" & "result failure")
0056             if (expectedFailure.isEmpty() ^ result.isEmpty()) {
0057                 DelayedOutput::self().push(result.isEmpty() ? FAILED_TO_FAIL().arg(it.key(), expectedFailure,
0058                                                                                    objectInformation(object)) :
0059                                            FAIL().arg(it.key(), result, objectInformation(object)));
0060                 return false;
0061             }
0062 
0063             if (!expectedFailure.isEmpty())
0064                 qDebug() << EXPECTED_FAIL().arg(it.key(), expectedFailure, objectInformation(object)).toUtf8().data();
0065         }
0066 
0067         return true;
0068     }
0069 
0070 private:
0071     QVariantMap expectedFailures(const QVariantMap& testData)
0072     {
0073         if (!testData.contains(EXPECT_FAIL()))
0074             return QVariantMap();
0075 
0076         return testData[EXPECT_FAIL()].toMap();
0077     }
0078     static QString noSuchTest(const QVariant&, T)
0079     {
0080         return TEST_NOT_FOUND();
0081     }
0082     static QString objectInformation(T)
0083     {
0084         return QString();
0085     }
0086     QHash<QString, TestFunction> m_testFunctions;
0087 
0088     TestSuite() { }
0089     Q_DISABLE_COPY(TestSuite)
0090 
0091     friend KDEVPLATFORMTESTS_EXPORT TestSuite<Declaration*>& declarationTestSuite();
0092     friend KDEVPLATFORMTESTS_EXPORT TestSuite<DUContext*>& contextTestSuite();
0093     friend KDEVPLATFORMTESTS_EXPORT TestSuite<AbstractType::Ptr>& typeTestSuite();
0094 };
0095 
0096 template<class T>
0097 inline bool runTests(const QVariantMap& data, T object)
0098 {
0099     return TestSuite<T>::get().runTests(data, object);
0100 }
0101 
0102 ///TODO: Once we can use C++11, see whether this can be cleaned up by extern templates
0103 template<>
0104 inline TestSuite<Declaration*>& TestSuite<Declaration*>::get()
0105 {
0106     return declarationTestSuite();
0107 }
0108 
0109 template<>
0110 inline TestSuite<DUContext*>& TestSuite<DUContext*>::get()
0111 {
0112     return contextTestSuite();
0113 }
0114 
0115 template<>
0116 inline TestSuite<AbstractType::Ptr>& TestSuite<AbstractType::Ptr>::get()
0117 {
0118     return typeTestSuite();
0119 }
0120 }
0121 
0122 #endif //KDEVPLATFORM_TESTSUITE_H