summaryrefslogtreecommitdiff
path: root/tests/manual/features/tst_features.cpp
blob: 722e0c39a5061a9250a643c0bbda7727ae6c0c51 (plain)
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0

#include <QtTest>
#include <QFile>
#include <QCoreApplication>

enum {
    Gcc11 = 1,
    Gcc98 = 2,
    Clang = 4,
    Extern = 8,

    First = Gcc11,
    Last = Extern
};

struct Data
{
    Data()
    {}

    Data(QByteArray c, uint f = 0)
        : code(c), expectedFailure(f)
    {}

    QByteArray code;
    uint expectedFailure;
};

Q_DECLARE_METATYPE(Data)

class tst_Features : public QObject
{
    Q_OBJECT

public:
    tst_Features() {}

private slots:
    void feature();
    void feature_data();
};

void tst_Features::feature()
{
    QFETCH(Data, data);

    QByteArray mainFile = "main.cpp";

    QFile source(mainFile);
    QVERIFY(source.open(QIODevice::ReadWrite | QIODevice::Truncate));
    QByteArray fullCode =
        "#include <vector>\n"
        "#include <string>\n\n"
        "using namespace std;\n\n"
        + data.code + "\n";
    source.write(fullCode);
    source.close();

    for (uint i = First; i <= Last; i *= 2) {
        QByteArray compiler;
        if (i & Gcc11)
            compiler = "g++ -Werror -std=c++0x -c";
        else if (i & Gcc98)
            compiler = "g++ -Werror -std=c++98 -c";
        else if (i & Clang)
            compiler = "clang++ -Werror -std=c++11 -c";
        else if (i & Extern)
            compiler = qgetenv("QTC_COMPILER_PATH");

        if (compiler.isEmpty())
            continue;

        QProcess proc;
        proc.start(compiler + " " + mainFile);
        proc.waitForFinished();
        QByteArray output = proc.readAllStandardOutput();
        QByteArray error = proc.readAllStandardError();
        bool compileFailure = proc.exitCode() != 0;
        bool ok = compileFailure == bool(data.expectedFailure & i);
        if (!ok) {
            qDebug() << "\n------------------ CODE --------------------";
            qDebug() << fullCode;
            //qDebug() << "\n------------------ CODE --------------------";
            //qDebug() << ".pro: " << qPrintable(proFile.fileName());
            qDebug() << "Compiler: " << compiler;
            qDebug() << "Error: " << error;
            qDebug() << "Output: " << output;
            qDebug() << "Code: " << fullCode;
            qDebug() << "\n------------------ CODE --------------------";
        }
        QVERIFY(ok);
    }
}

void tst_Features::feature_data()
{
    QTest::addColumn<Data>("data");

    // Self-test. "$" should be expected to fail in any case.
    QTest::newRow("checkfail")
            << Data("$", -1);

    QTest::newRow("auto-keyword")
            << Data("auto i = vector<int>::iterator();", Gcc98);

    QTest::newRow("ranged-for")
            << Data("int foo() { int s = 0; vector<int> v; "
                    "for (int i: v) { s += v[i]; } return s; }", Gcc98);

    QTest::newRow("in-class-member-initialization")
            << Data("struct S { int a = 1; }; int main() { S s; return s.a; }", Gcc98);
}

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    tst_Features test;
    return QTest::qExec(&test, argc, argv);
}

#include "tst_features.moc"