typehierarchybuilder_test.cpp 6.22 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** 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 Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "cpptoolsplugin.h"

#include "cppmodelmanagerinterface.h"
33
#include "cpptoolstestcase.h"
34 35 36
#include "typehierarchybuilder.h"

#include <cplusplus/Overview.h>
37
#include <cplusplus/SymbolVisitor.h>
38 39 40 41 42 43 44 45 46
#include <utils/fileutils.h>

#include <QDir>
#include <QtTest>

using namespace CPlusPlus;
using namespace CppTools;
using namespace CppTools::Internal;

47 48
Q_DECLARE_METATYPE(QList<Tests::TestDocument>)

49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
namespace {

bool hierarchySorter(const TypeHierarchy &h1, const TypeHierarchy &h2)
{
    Overview oo;
    return oo.prettyName(h1.symbol()->name()) < oo.prettyName(h2.symbol()->name());
}

QString toString(const TypeHierarchy &hierarchy, int indent = 0)
{
    Symbol *symbol = hierarchy.symbol();
    QString result = QString(indent, QLatin1Char(' '))
        + Overview().prettyName(symbol->name()) + QLatin1Char('\n');

    QList<TypeHierarchy> sortedHierarchy = hierarchy.hierarchy();
    qSort(sortedHierarchy.begin(), sortedHierarchy.end(), hierarchySorter);
    foreach (TypeHierarchy childHierarchy, sortedHierarchy)
        result += toString(childHierarchy, indent + 2);
    return result;
}

class FindFirstClassInDocument: private SymbolVisitor
{
public:
    FindFirstClassInDocument() : m_clazz(0) {}

    Class *operator()(const Document::Ptr &document)
    {
        accept(document->globalNamespace());
        return m_clazz;
    }

private:
    bool preVisit(Symbol *symbol)
    {
        if (m_clazz)
            return false;

        if (Class *c = symbol->asClass()) {
            m_clazz = c;
            return false;
        }

        return true;
    }

95
private:
96 97 98
    Class *m_clazz;
};

99
class TypeHierarchyBuilderTestCase : public CppTools::Tests::TestCase
100 101
{
public:
102 103 104 105
    TypeHierarchyBuilderTestCase(const QList<Tests::TestDocument> &documents,
                                 const QString &expectedHierarchy)
        : m_documents(documents),
          m_expectedHierarchy(expectedHierarchy)
106
    {}
107 108 109 110 111

    void run()
    {
        // Write files
        QStringList filePaths;
112 113 114
        foreach (const Tests::TestDocument &document, m_documents) {
            QVERIFY(document.writeToDisk());
            filePaths << document.filePath();
115 116 117
        }

        // Parse files
118 119
        QVERIFY(parseFiles(filePaths));
        const Snapshot snapshot = globalSnapshot();
120 121

        // Get class for which to generate the hierarchy
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
        const Document::Ptr firstDocument = snapshot.document(filePaths.first());
        Class *clazz = FindFirstClassInDocument()(firstDocument);
        QVERIFY(clazz);

        // Generate and compare hierarchies
        TypeHierarchyBuilder typeHierarchyBuilder(clazz, snapshot);
        const TypeHierarchy hierarchy = typeHierarchyBuilder.buildDerivedTypeHierarchy();

        const QString actualHierarchy = toString(hierarchy);
//        Uncomment for updating/generating reference data:
//        qDebug() << actualHierarchy;
        QCOMPARE(actualHierarchy, m_expectedHierarchy);
    }

private:
137
    QList<Tests::TestDocument> m_documents;
138 139 140 141 142 143 144
    QString m_expectedHierarchy;
};

} // anonymous namespace

void CppToolsPlugin::test_typehierarchy_data()
{
145
    QTest::addColumn<QList<Tests::TestDocument> >("documents");
146 147
    QTest::addColumn<QString>("expectedHierarchy");

148
    typedef Tests::TestDocument TestDocument;
149 150 151

    QTest::newRow("basic-single-document")
        << (QList<TestDocument>()
152 153 154 155 156 157
            << TestDocument("a.h",
                            "class A {};\n"
                            "class B : public A {};\n"
                            "class C1 : public B {};\n"
                            "class C2 : public B {};\n"
                            "class D : public C1 {};\n"))
158 159 160 161 162 163 164 165 166
        << QString::fromLatin1(
            "A\n"
            "  B\n"
            "    C1\n"
            "      D\n"
            "    C2\n" );

    QTest::newRow("basic-multiple-documents")
        << (QList<TestDocument>()
167 168 169 170 171 172 173 174 175 176 177 178 179 180
            << TestDocument("a.h",
                            "class A {};")
            << TestDocument("b.h",
                            "#include \"a.h\"\n"
                            "class B : public A {};")
            << TestDocument("c1.h",
                            "#include \"b.h\"\n"
                            "class C1 : public B {};")
            << TestDocument("c2.h",
                            "#include \"b.h\"\n"
                            "class C2 : public B {};")
            << TestDocument("d.h",
                            "#include \"c1.h\"\n"
                            "class D : public C1 {};"))
181 182 183 184 185 186 187 188 189 190 191
        << QString::fromLatin1(
            "A\n"
            "  B\n"
            "    C1\n"
            "      D\n"
            "    C2\n"
            );
}

void CppToolsPlugin::test_typehierarchy()
{
192
    QFETCH(QList<Tests::TestDocument>, documents);
193 194
    QFETCH(QString, expectedHierarchy);

195
    TypeHierarchyBuilderTestCase testCase(documents, expectedHierarchy);
196 197
    testCase.run();
}