~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to tests/auto/corelib/tools/qsharedpointer/externaltests.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the test suite of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL$
 
9
** Commercial License Usage
 
10
** Licensees holding valid commercial Qt licenses may use this file in
 
11
** accordance with the commercial license agreement provided with the
 
12
** Software or, alternatively, in accordance with the terms contained in
 
13
** a written agreement between you and Digia.  For licensing terms and
 
14
** conditions see http://qt.digia.com/licensing.  For further information
 
15
** use the contact form at http://qt.digia.com/contact-us.
 
16
**
 
17
** GNU Lesser General Public License Usage
 
18
** Alternatively, this file may be used under the terms of the GNU Lesser
 
19
** General Public License version 2.1 as published by the Free Software
 
20
** Foundation and appearing in the file LICENSE.LGPL included in the
 
21
** packaging of this file.  Please review the following information to
 
22
** ensure the GNU Lesser General Public License version 2.1 requirements
 
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
24
**
 
25
** In addition, as a special exception, Digia gives you certain additional
 
26
** rights.  These rights are described in the Digia Qt LGPL Exception
 
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
28
**
 
29
** GNU General Public License Usage
 
30
** Alternatively, this file may be used under the terms of the GNU
 
31
** General Public License version 3.0 as published by the Free Software
 
32
** Foundation and appearing in the file LICENSE.GPL included in the
 
33
** packaging of this file.  Please review the following information to
 
34
** ensure the GNU General Public License version 3.0 requirements will be
 
35
** met: http://www.gnu.org/copyleft/gpl.html.
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
 
 
43
#include "externaltests.h"
 
44
 
 
45
#include <QtCore/QTemporaryFile>
 
46
#include <QtCore/QTemporaryDir>
 
47
#include <QtCore/QProcess>
 
48
#include <QtCore/QByteArray>
 
49
#include <QtCore/QString>
 
50
#include <QtCore/QFileInfo>
 
51
#include <QtCore/QDir>
 
52
#include <QtCore/QDirIterator>
 
53
#include <QtCore/QDateTime>
 
54
#include <QtCore/QDebug>
 
55
#include <QtCore/QLibraryInfo>
 
56
 
 
57
#ifndef DEFAULT_MAKESPEC
 
58
# error DEFAULT_MAKESPEC not defined
 
59
#endif
 
60
 
 
61
#ifdef Q_OS_UNIX
 
62
# include <fcntl.h>
 
63
# include <unistd.h>
 
64
#endif
 
65
 
 
66
static QString makespec()
 
67
{
 
68
    static const char default_makespec[] = DEFAULT_MAKESPEC;
 
69
    if (default_makespec[0] == '/')
 
70
        return QString::fromLatin1(default_makespec);
 
71
 
 
72
    const char *p;
 
73
    for (p = default_makespec + sizeof(default_makespec) - 1; p >= default_makespec; --p)
 
74
        if (*p == '/' || *p == '\\')
 
75
            break;
 
76
 
 
77
    return QString::fromLatin1(p + 1);
 
78
}
 
79
 
 
80
QT_BEGIN_NAMESPACE
 
81
namespace QTest {
 
82
    class QExternalProcess: public QProcess
 
83
    {
 
84
    protected:
 
85
#ifdef Q_OS_UNIX
 
86
        void setupChildProcess()
 
87
        {
 
88
            // run in user code
 
89
            QProcess::setupChildProcess();
 
90
 
 
91
            if (processChannelMode() == ForwardedChannels) {
 
92
                // reopen /dev/tty into stdin
 
93
                int fd = ::open("/dev/tty", O_RDONLY);
 
94
                if (fd == -1)
 
95
                    return;
 
96
                ::dup2(fd, 0);
 
97
                ::close(fd);
 
98
            }
 
99
        }
 
100
#endif
 
101
    };
 
102
 
 
103
    class QExternalTestPrivate
 
104
    {
 
105
    public:
 
106
        QExternalTestPrivate()
 
107
            : qtModules(QExternalTest::QtCore | QExternalTest::QtGui | QExternalTest::QtTest),
 
108
              appType(QExternalTest::AutoApplication),
 
109
              temporaryDir(0), exitCode(-1)
 
110
        {
 
111
        }
 
112
        ~QExternalTestPrivate()
 
113
        {
 
114
            clear();
 
115
        }
 
116
 
 
117
        enum Target { Compile, Link, Run };
 
118
 
 
119
        QList<QByteArray> qmakeLines;
 
120
        QStringList extraProgramSources;
 
121
        QByteArray programHeader;
 
122
        QExternalTest::QtModules qtModules;
 
123
        QExternalTest::ApplicationType appType;
 
124
 
 
125
        QString temporaryDirPath;
 
126
        QTemporaryDir *temporaryDir;
 
127
        QByteArray sourceCode;
 
128
        QByteArray std_out;
 
129
        QByteArray std_err;
 
130
        int exitCode;
 
131
        QExternalTest::Stage failedStage;
 
132
 
 
133
        void clear();
 
134
        bool tryCompile(const QByteArray &body);
 
135
        bool tryLink(const QByteArray &body);
 
136
        bool tryRun(const QByteArray &body);
 
137
 
 
138
    private:
 
139
        void removeTemporaryDirectory();
 
140
        bool createTemporaryDirectory();
 
141
        bool prepareSourceCode(const QByteArray &body);
 
142
        bool createProjectFile();
 
143
        bool runQmake();
 
144
        bool runMake(Target target);
 
145
        bool commonSetup(const QByteArray &body);
 
146
    };
 
147
 
 
148
    QExternalTest::QExternalTest()
 
149
        : d(new QExternalTestPrivate)
 
150
    {
 
151
    }
 
152
 
 
153
    QExternalTest::~QExternalTest()
 
154
    {
 
155
        delete d;
 
156
    }
 
157
 
 
158
    QList<QByteArray> QExternalTest::qmakeSettings() const
 
159
    {
 
160
        return d->qmakeLines;
 
161
    }
 
162
 
 
163
    void QExternalTest::setQmakeSettings(const QList<QByteArray> &settings)
 
164
    {
 
165
        d->qmakeLines = settings;
 
166
    }
 
167
 
 
168
    QExternalTest::QtModules QExternalTest::qtModules() const
 
169
    {
 
170
        return d->qtModules;
 
171
    }
 
172
 
 
173
    void QExternalTest::setQtModules(QtModules modules)
 
174
    {
 
175
        d->qtModules = modules;
 
176
    }
 
177
 
 
178
    QExternalTest::ApplicationType QExternalTest::applicationType() const
 
179
    {
 
180
        return d->appType;
 
181
    }
 
182
 
 
183
    void QExternalTest::setApplicationType(ApplicationType type)
 
184
    {
 
185
        d->appType = type;
 
186
    }
 
187
 
 
188
    QStringList QExternalTest::extraProgramSources() const
 
189
    {
 
190
        return d->extraProgramSources;
 
191
    }
 
192
 
 
193
    void QExternalTest::setExtraProgramSources(const QStringList &extra)
 
194
    {
 
195
        d->extraProgramSources = extra;
 
196
    }
 
197
 
 
198
    QByteArray QExternalTest::programHeader() const
 
199
    {
 
200
        return d->programHeader;
 
201
    }
 
202
 
 
203
    void QExternalTest::setProgramHeader(const QByteArray &header)
 
204
    {
 
205
        d->programHeader = header;
 
206
    }
 
207
 
 
208
    bool QExternalTest::tryCompile(const QByteArray &body)
 
209
    {
 
210
        return d->tryCompile(body) && d->exitCode == 0;
 
211
    }
 
212
 
 
213
    bool QExternalTest::tryLink(const QByteArray &body)
 
214
    {
 
215
        return d->tryLink(body) && d->exitCode == 0;
 
216
    }
 
217
 
 
218
    bool QExternalTest::tryRun(const QByteArray &body)
 
219
    {
 
220
        return d->tryRun(body) && d->exitCode == 0;
 
221
    }
 
222
 
 
223
    bool QExternalTest::tryCompileFail(const QByteArray &body)
 
224
    {
 
225
        return d->tryCompile(body) && d->exitCode != 0;
 
226
    }
 
227
 
 
228
    bool QExternalTest::tryLinkFail(const QByteArray &body)
 
229
    {
 
230
        return d->tryLink(body) && d->exitCode != 0;
 
231
    }
 
232
 
 
233
    bool QExternalTest::tryRunFail(const QByteArray &body)
 
234
    {
 
235
        return d->tryRun(body) && d->exitCode != 0;
 
236
    }
 
237
 
 
238
    QExternalTest::Stage QExternalTest::failedStage() const
 
239
    {
 
240
        return d->failedStage;
 
241
    }
 
242
 
 
243
    int QExternalTest::exitCode() const
 
244
    {
 
245
        return d->exitCode;
 
246
    }
 
247
 
 
248
    QByteArray QExternalTest::fullProgramSource() const
 
249
    {
 
250
        return d->sourceCode;
 
251
    }
 
252
 
 
253
    QByteArray QExternalTest::standardOutput() const
 
254
    {
 
255
        return d->std_out;
 
256
    }
 
257
 
 
258
    QByteArray QExternalTest::standardError() const
 
259
    {
 
260
        return d->std_err;
 
261
    }
 
262
 
 
263
    QString QExternalTest::errorReport() const
 
264
    {
 
265
        const char *stage = 0;
 
266
        switch (d->failedStage) {
 
267
        case FileStage:
 
268
            stage = "creating files";
 
269
            break;
 
270
        case QmakeStage:
 
271
            stage = "executing qmake";
 
272
            break;
 
273
        case CompilationStage:
 
274
            stage = "during compilation";
 
275
            break;
 
276
        case LinkStage:
 
277
            stage = "during linking";
 
278
            break;
 
279
        case RunStage:
 
280
            stage = "executing program";
 
281
            break;
 
282
        }
 
283
 
 
284
        QString report = QString::fromLatin1(
 
285
            "External test failed %1 with exit code %4\n"
 
286
            "==== standard error: ====\n"
 
287
            "%2\n"
 
288
            "==== standard output: ====\n"
 
289
            "%3\n"
 
290
            "==== ====\n");
 
291
        return report.arg(QString::fromLatin1(stage),
 
292
                          QString::fromLocal8Bit(d->std_err),
 
293
                          QString::fromLocal8Bit(d->std_out))
 
294
            .arg(d->exitCode);
 
295
    }
 
296
 
 
297
    // actual execution code
 
298
    void QExternalTestPrivate::clear()
 
299
    {
 
300
        delete temporaryDir;
 
301
        temporaryDir = 0;
 
302
        sourceCode.clear();
 
303
        std_out.clear();
 
304
        std_err.clear();
 
305
        exitCode = -1;
 
306
        failedStage = QExternalTest::FileStage;
 
307
    }
 
308
 
 
309
    bool QExternalTestPrivate::prepareSourceCode(const QByteArray &body)
 
310
    {
 
311
        sourceCode.clear();
 
312
        sourceCode.reserve(8192);
 
313
 
 
314
        sourceCode += programHeader;
 
315
 
 
316
        // Add Qt header includes
 
317
        if (qtModules & QExternalTest::QtCore)
 
318
            sourceCode += "#include <QtCore/QtCore>\n";
 
319
        if (qtModules & QExternalTest::QtGui)
 
320
            sourceCode += "#include <QtGui/QtGui>\n";
 
321
        if (qtModules & QExternalTest::QtNetwork)
 
322
            sourceCode += "#include <QtNetwork/QtNetwork>\n";
 
323
        if (qtModules & QExternalTest::QtXml)
 
324
            sourceCode += "#include <QtXml/QtXml>\n";
 
325
        if (qtModules & QExternalTest::QtXmlPatterns)
 
326
            sourceCode += "#include <QtXmlPatterns/QtXmlPatterns>\n";
 
327
        if (qtModules & QExternalTest::QtOpenGL)
 
328
            sourceCode += "#include <QtOpenGL/QtOpenGL>\n";
 
329
        if (qtModules & QExternalTest::QtSql)
 
330
            sourceCode += "#include <QtSql/QtSql>\n";
 
331
        if (qtModules & QExternalTest::QtSvg)
 
332
            sourceCode += "#include <QtSvg/QtSvg>\n";
 
333
        if (qtModules & QExternalTest::QtScript)
 
334
            sourceCode += "#include <QtScript/QtScript>\n";
 
335
        if (qtModules & QExternalTest::QtTest)
 
336
            sourceCode += "#include <QtTest/QtTest>\n";
 
337
        if (qtModules & QExternalTest::QtDBus)
 
338
            sourceCode += "#include <QtDBus/QtDBus>\n";
 
339
        if (qtModules & QExternalTest::QtWebKit)
 
340
            sourceCode += "#include <QtWebKit/QtWebKit>\n";
 
341
        if (qtModules & QExternalTest::Phonon)
 
342
            sourceCode += "#include <Phonon/Phonon>\n";
 
343
        sourceCode +=
 
344
            "#include <stdlib.h>\n"
 
345
            "#include <stddef.h>\n";
 
346
 
 
347
        sourceCode +=
 
348
            "\n"
 
349
            "void q_external_test_user_code()\n"
 
350
            "{\n"
 
351
            "#include \"user_code.cpp\"\n"
 
352
            "}\n"
 
353
            "\n"
 
354
            "#ifdef Q_OS_WIN\n"
 
355
            "#include <windows.h>\n"
 
356
            "#if defined(Q_CC_MSVC) && !defined(Q_OS_WINCE)\n"
 
357
            "#include <crtdbg.h>\n"
 
358
            "#endif\n"
 
359
            "static void q_test_setup()\n"
 
360
            "{\n"
 
361
            "    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);\n"
 
362
            "}\n"
 
363
            "static int __cdecl CrtDbgHook(int /*reportType*/, char * /*message*/, int * /*returnValue*/)\n"
 
364
            "{\n"
 
365
            "    return TRUE;\n"
 
366
            "}\n"
 
367
            "#else\n"
 
368
            "static void q_test_setup() { }\n"
 
369
            "#endif\n"
 
370
            "int main(int argc, char **argv)\n"
 
371
            "{\n"
 
372
            "#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) && !defined(Q_OS_WINCE)\n"
 
373
            "    _CrtSetReportHook2(_CRT_RPTHOOK_INSTALL, CrtDbgHook);\n"
 
374
            "#endif\n";
 
375
 
 
376
        switch (appType) {
 
377
        applicationless:
 
378
        case QExternalTest::Applicationless:
 
379
            sourceCode +=
 
380
                "    (void)argc; (void)argv;\n";
 
381
            break;
 
382
 
 
383
        coreapplication:
 
384
        case QExternalTest::QCoreApplication:
 
385
            sourceCode +=
 
386
                "    QCoreApplication app(argc, argv);\n";
 
387
            break;
 
388
 
 
389
        guiapplication:
 
390
        case QExternalTest::QGuiApplication:
 
391
            sourceCode +=
 
392
                "    QGuiApplication app(argc, argv);\n";
 
393
            break;
 
394
 
 
395
        widgetsapplication:
 
396
        case QExternalTest::QApplication:
 
397
            sourceCode +=
 
398
                "    QApplication app(argc, argv);\n";
 
399
            break;
 
400
 
 
401
        case QExternalTest::AutoApplication:
 
402
            if (qtModules & QExternalTest::QtWidgets)
 
403
                goto widgetsapplication;
 
404
            if (qtModules & QExternalTest::QtGui)
 
405
                goto guiapplication;
 
406
            if (qtModules == 0)
 
407
                goto applicationless;
 
408
            goto coreapplication;
 
409
        }
 
410
 
 
411
        sourceCode +=
 
412
            "    q_test_setup();\n"
 
413
            "    q_external_test_user_code();\n"
 
414
            "    return 0;\n"
 
415
            "}\n";
 
416
 
 
417
        QFile sourceFile(temporaryDirPath + QLatin1String("/project.cpp"));
 
418
        if (!sourceFile.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
 
419
            std_err = sourceFile.errorString().toLocal8Bit();
 
420
            return false;
 
421
        }
 
422
 
 
423
        sourceFile.write(sourceCode);
 
424
        sourceFile.close();
 
425
 
 
426
        sourceFile.setFileName(temporaryDirPath + QLatin1String("/user_code.cpp"));
 
427
        if (!sourceFile.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
 
428
            std_err = sourceFile.errorString().toLocal8Bit();
 
429
            return false;
 
430
        }
 
431
        sourceFile.write(body);
 
432
 
 
433
        return true;
 
434
    }
 
435
 
 
436
    bool QExternalTestPrivate::createTemporaryDirectory()
 
437
    {
 
438
        delete temporaryDir;
 
439
        temporaryDir = new QTemporaryDir;
 
440
        if (temporaryDir->isValid()) {
 
441
            temporaryDirPath = temporaryDir->path();
 
442
            return true;
 
443
        } else {
 
444
            delete temporaryDir;
 
445
            temporaryDir = 0;
 
446
            return false;
 
447
        }
 
448
    }
 
449
 
 
450
    bool QExternalTestPrivate::createProjectFile()
 
451
    {
 
452
        if (temporaryDirPath.isEmpty())
 
453
            qWarning() << "Temporary directory is expected to be non-empty";
 
454
 
 
455
        QFile projectFile(temporaryDirPath + QLatin1String("/project.pro"));
 
456
        if (!projectFile.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
 
457
            std_err = projectFile.errorString().toLocal8Bit();
 
458
            return false;
 
459
        }
 
460
 
 
461
        projectFile.write(
 
462
            "TEMPLATE = app\n"
 
463
            "\n"
 
464
            "TARGET   = externaltest\n"
 
465
            "CONFIG   -= app_bundle\n"        // for the Mac
 
466
            "CONFIG   -= debug_and_release\n"
 
467
            "CONFIG   += console\n"
 
468
            "DESTDIR  = .\n"
 
469
            "OBJECTS_DIR = .\n"
 
470
            "UI_DIR   = .\n"
 
471
            "MOC_DIR  = .\n"
 
472
            "RCC_DIR  = .\n"
 
473
            "HEADERS  +=\n"
 
474
            "SOURCES  += project.cpp\n"
 
475
            "QT       -= core gui\n"
 
476
            "INCLUDEPATH += . ");
 
477
 
 
478
        QString workingDir = QDir::currentPath();
 
479
        if (extraProgramSources.count() > 0)
 
480
            workingDir = QFileInfo(extraProgramSources.first()).absolutePath();
 
481
        projectFile.write(QFile::encodeName(workingDir));
 
482
 
 
483
#ifndef QT_NO_DEBUG
 
484
            projectFile.write("\nCONFIG  += debug\n");
 
485
#else
 
486
            projectFile.write("\nCONFIG  += release\n");
 
487
#endif
 
488
 
 
489
        QByteArray extraSources = QFile::encodeName(extraProgramSources.join(' '));
 
490
        if (!extraSources.isEmpty()) {
 
491
            projectFile.write("SOURCES  += ");
 
492
            projectFile.write(extraSources);
 
493
            projectFile.putChar('\n');
 
494
        }
 
495
 
 
496
        // Add Qt modules
 
497
        if (qtModules & QExternalTest::QtCore)
 
498
            projectFile.write("QT += core\n");
 
499
        if (qtModules & QExternalTest::QtGui)
 
500
            projectFile.write("QT += gui\n");
 
501
        if (qtModules & QExternalTest::QtNetwork)
 
502
            projectFile.write("QT += network\n");
 
503
        if (qtModules & QExternalTest::QtXml)
 
504
            projectFile.write("QT += xml\n");
 
505
        if (qtModules & QExternalTest::QtXmlPatterns)
 
506
            projectFile.write("QT += xmlpatterns\n");
 
507
        if (qtModules & QExternalTest::QtOpenGL)
 
508
            projectFile.write("QT += opengl\n");
 
509
        if (qtModules & QExternalTest::QtSql)
 
510
            projectFile.write("QT += sql\n");
 
511
        if (qtModules & QExternalTest::QtSvg)
 
512
            projectFile.write("QT += svg\n");
 
513
        if (qtModules & QExternalTest::QtScript)
 
514
            projectFile.write("QT += script\n");
 
515
        if (qtModules & QExternalTest::QtTest)
 
516
            projectFile.write("QT += testlib\n");
 
517
        if (qtModules & QExternalTest::QtDBus)
 
518
            projectFile.write("QT += dbus\n");
 
519
        if (qtModules & QExternalTest::QtWebKit)
 
520
            projectFile.write("QT += webkit\n");
 
521
        if (qtModules & QExternalTest::Phonon)
 
522
            projectFile.write("QT += phonon\n");
 
523
 
 
524
        projectFile.write("\n### User-specified settings start ###\n");
 
525
        foreach (QByteArray line, qmakeLines) {
 
526
            projectFile.write(line);
 
527
            projectFile.write("\n");
 
528
        }
 
529
        projectFile.write("\n### User-specified settings end ###\n");
 
530
 
 
531
        // Use qmake to just compile:
 
532
        projectFile.write(
 
533
            "\n"
 
534
            "test_compile.depends        += $(OBJECTS)\n"
 
535
            "QMAKE_EXTRA_TARGETS += test_compile\n");
 
536
 
 
537
        // Use qmake to run the app too:
 
538
        projectFile.write(
 
539
            "\n"
 
540
            "unix:test_run.commands     = ./$(QMAKE_TARGET)\n"
 
541
            "else:test_run.commands     = $(QMAKE_TARGET)\n"
 
542
            "embedded:test_run.commands += -qws\n"
 
543
            "QMAKE_EXTRA_TARGETS += test_run\n");
 
544
 
 
545
        // Use qmake to debug:
 
546
        projectFile.write(
 
547
            "\n"
 
548
            "*-g++* {\n"
 
549
            "    unix:test_debug.commands      =  gdb --args ./$(QMAKE_TARGET)\n"
 
550
            "    else:test_debug.commands      = gdb --args $(QMAKE_TARGET)\n"
 
551
            "    embedded:test_debug.commands += -qws\n"
 
552
            "    QMAKE_EXTRA_TARGETS += test_debug\n"
 
553
            "}\n");
 
554
 
 
555
        // Also use qmake to run the app with valgrind:
 
556
        projectFile.write(
 
557
            "\n"
 
558
            "unix:test_valgrind.commands      = valgrind ./$(QMAKE_TARGET)\n"
 
559
            "else:test_valgrind.commands      = valgrind $(QMAKE_TARGET)\n"
 
560
            "embedded:test_valgrind.commands += -qws\n"
 
561
            "QMAKE_EXTRA_TARGETS    += test_valgrind\n");
 
562
 
 
563
        return true;
 
564
    }
 
565
 
 
566
    bool QExternalTestPrivate::runQmake()
 
567
    {
 
568
        if (temporaryDirPath.isEmpty())
 
569
            qWarning() << "Temporary directory is expected to be non-empty";
 
570
 
 
571
        if (!createProjectFile())
 
572
            return false;
 
573
 
 
574
        failedStage = QExternalTest::QmakeStage;
 
575
        QProcess qmake;
 
576
        QStringList args;
 
577
        args << QLatin1String("-makefile")
 
578
             << QLatin1String("-spec")
 
579
             << makespec()
 
580
             << QLatin1String("project.pro");
 
581
        qmake.setWorkingDirectory(temporaryDirPath);
 
582
 
 
583
        QString cmd = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmake";
 
584
#ifdef Q_OS_WIN
 
585
        cmd.append(".exe");
 
586
#endif
 
587
        if (!QFile::exists(cmd)) {
 
588
            cmd = "qmake";
 
589
            qWarning("qmake from build not found, fallback to PATH's qmake");
 
590
        }
 
591
 
 
592
        qmake.start(cmd, args);
 
593
 
 
594
        std_out += "### --- stdout from qmake --- ###\n";
 
595
        std_err += "### --- stderr from qmake --- ###\n";
 
596
        bool ok = qmake.waitForStarted();
 
597
        if (!ok) {
 
598
            exitCode = 255;
 
599
            std_err += "qmake: ";
 
600
            std_err += qmake.errorString().toLocal8Bit();
 
601
        } else {
 
602
            ok = qmake.waitForFinished();
 
603
            exitCode = qmake.exitCode();
 
604
 
 
605
            std_out += qmake.readAllStandardOutput();
 
606
            std_err += qmake.readAllStandardError();
 
607
        }
 
608
 
 
609
        return ok && exitCode == 0;
 
610
    }
 
611
 
 
612
    bool QExternalTestPrivate::runMake(Target target)
 
613
    {
 
614
        if (temporaryDirPath.isEmpty())
 
615
            qWarning() << "Temporary directory is expected to be non-empty";
 
616
 
 
617
        QExternalProcess make;
 
618
        make.setWorkingDirectory(temporaryDirPath);
 
619
 
 
620
        QStringList environment = QProcess::systemEnvironment();
 
621
        environment += QLatin1String("LC_ALL=C");
 
622
        make.setEnvironment(environment);
 
623
 
 
624
        QStringList args;
 
625
        QProcess::ProcessChannelMode channelMode = QProcess::SeparateChannels;
 
626
        if (target == Compile) {
 
627
            args << QLatin1String("test_compile");
 
628
        } else if (target == Run) {
 
629
            QByteArray run = qgetenv("QTEST_EXTERNAL_RUN");
 
630
            if (run == "valgrind")
 
631
                args << QLatin1String("test_valgrind");
 
632
            else if (run == "debug")
 
633
                args << QLatin1String("test_debug");
 
634
            else
 
635
                args << QLatin1String("test_run");
 
636
            if (!run.isEmpty())
 
637
                channelMode = QProcess::ForwardedChannels;
 
638
        }
 
639
 
 
640
        make.setProcessChannelMode(channelMode);
 
641
 
 
642
        static const char makes[] =
 
643
            "nmake.exe\0" //for visual c++
 
644
            "mingw32-make.exe\0" //for mingw
 
645
            "gmake\0"
 
646
            "make\0";
 
647
        for (const char *p = makes; *p; p += strlen(p) + 1) {
 
648
            make.start(QLatin1String(p), args);
 
649
            if (make.waitForStarted())
 
650
                break;
 
651
        }
 
652
 
 
653
        if (make.state() != QProcess::Running) {
 
654
            exitCode = 255;
 
655
            std_err += "make: ";
 
656
            std_err += make.errorString().toLocal8Bit();
 
657
            return false;
 
658
        }
 
659
 
 
660
        make.closeWriteChannel();
 
661
        bool ok = make.waitForFinished(channelMode == QProcess::ForwardedChannels ? -1 : 60000);
 
662
        if (!ok)
 
663
            make.terminate();
 
664
        exitCode = make.exitCode();
 
665
        std_out += make.readAllStandardOutput();
 
666
        std_err += make.readAllStandardError();
 
667
 
 
668
        return ok;
 
669
    }
 
670
 
 
671
    bool QExternalTestPrivate::commonSetup(const QByteArray &body)
 
672
    {
 
673
        clear();
 
674
 
 
675
        if (!createTemporaryDirectory())
 
676
            return false;
 
677
        if (!createProjectFile())
 
678
            return false;
 
679
        if (!prepareSourceCode(body))
 
680
            return false;
 
681
        if (!runQmake())
 
682
            return false;
 
683
        return true;
 
684
    }
 
685
 
 
686
    bool QExternalTestPrivate::tryCompile(const QByteArray &body)
 
687
    {
 
688
        if (!commonSetup(body))
 
689
            return false;
 
690
 
 
691
        // compile
 
692
        failedStage = QExternalTest::CompilationStage;
 
693
        std_out += "\n### --- stdout from make (compilation) --- ###\n";
 
694
        std_err += "\n### --- stderr from make (compilation) --- ###\n";
 
695
        return runMake(Compile);
 
696
    }
 
697
 
 
698
    bool QExternalTestPrivate::tryLink(const QByteArray &body)
 
699
    {
 
700
        if (!tryCompile(body) || exitCode != 0)
 
701
            return false;
 
702
 
 
703
        // link
 
704
        failedStage = QExternalTest::LinkStage;
 
705
        std_out += "\n### --- stdout from make (linking) --- ###\n";
 
706
        std_err += "\n### --- stderr from make (linking) --- ###\n";
 
707
        return runMake(Link);
 
708
    }
 
709
 
 
710
    bool QExternalTestPrivate::tryRun(const QByteArray &body)
 
711
    {
 
712
        if (!tryLink(body) || exitCode != 0)
 
713
            return false;
 
714
 
 
715
        // run
 
716
        failedStage = QExternalTest::RunStage;
 
717
        std_out += "\n### --- stdout from process --- ###\n";
 
718
        std_err += "\n### --- stderr from process --- ###\n";
 
719
        return runMake(Run);
 
720
    }
 
721
}
 
722
QT_END_NAMESPACE