1
/****************************************************************************
2
**
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the test suite of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
43
#include <QtTest/QtTest>
44
45
#include <q3process.h>
46
#include <qregexp.h>
47
#include <qdebug.h>
48
49
QT_FORWARD_DECLARE_CLASS(Q3Process)
50
51
//TESTED_CLASS=
52
//TESTED_FILES=
53
54
class tst_Q3Process : public QObject
55
{
56
    Q_OBJECT
57
58
public:
59
    tst_Q3Process();
60
    virtual ~tst_Q3Process();
61
62
63
public slots:
64
    void init();
65
    void cleanup();
66
private slots:
67
    void readLineStdout_data();
68
    void readLineStdout();
69
    void readLineStderr_data();
70
    void readLineStderr();
71
    void communication_data();
72
    void communication();
73
74
    void canReadLineStdout_data();
75
    void canReadLineStdout();
76
    void canReadLineStderr_data();
77
    void canReadLineStderr();
78
    void startWithNoEnvironment();
79
    void startWithEmptyStringArgument();
80
    
81
protected slots:
82
    void processExited();
83
    void exitLoopSlot();
84
85
private:
86
    Q3Process *proc;
87
    QStringList linesReadStdout;
88
    QStringList linesReadStderr;
89
};
90
91
tst_Q3Process::tst_Q3Process()
92
    : proc(0)
93
{
94
}
95
96
tst_Q3Process::~tst_Q3Process()
97
{
98
}
99
100
void tst_Q3Process::init()
101
{
102
    linesReadStdout.clear();
103
    linesReadStderr.clear();
104
}
105
106
void tst_Q3Process::cleanup()
107
{
108
    if ( proc ) {
109
	proc->kill();
110
	delete proc;
111
	proc = 0;
112
    }
113
}
114
115
void tst_Q3Process::readLineStdout_data()
116
{
117
    QTest::addColumn<QString>("input");
118
    QTest::addColumn<QStringList>("res");
119
120
    QStringList l;
121
122
    QTest::newRow( "unix_0" ) << QString("a\nbc\ndef\nghij\n")
123
	<< (QStringList)( l << "a" << "bc" << "def" << "ghij" );
124
    l.clear();
125
    QTest::newRow( "unix_1" ) << QString("a\nbc\ndef\nghij")
126
	<< (QStringList)( l << "a" << "bc" << "def" << "ghij" );
127
    l.clear();
128
    QTest::newRow( "unix_2" ) << QString("a\nbc\n\ndef\nghij\n")
129
	<< (QStringList)( l << "a" << "bc" << "" << "def" << "ghij" );
130
    l.clear();
131
132
    QTest::newRow( "windows_0" ) << QString("a\r\nbc\r\ndef\r\nghij\r\n")
133
	<< (QStringList)( l << "a" << "bc" << "def" << "ghij" );
134
    l.clear();
135
    QTest::newRow( "windows_1" ) << QString("a\r\nbc\r\ndef\r\nghij")
136
	<< (QStringList)( l << "a" << "bc" << "def" << "ghij" );
137
    l.clear();
138
    QTest::newRow( "windows_2" ) << QString("a\r\nbc\r\n\r\ndef\r\nghij\r\n")
139
	<< (QStringList)( l << "a" << "bc" << "" << "def" << "ghij" );
140
    l.clear();
141
142
    QTest::newRow( "mixed_0" ) << QString("a\r\nbc\ndef\r\nghij\n")
143
	<< (QStringList)( l << "a" << "bc" << "def" << "ghij" );
144
    l.clear();
145
    QTest::newRow( "mixed_1" ) << QString("a\nbc\r\ndef\nghij\r\n")
146
	<< (QStringList)( l << "a" << "bc" << "def" << "ghij" );
147
    l.clear();
148
    QTest::newRow( "mixed_2" ) << QString("a\nbc\r\r\ndef\r\r\r\nghij\r\r\r\r\n")
149
	<< (QStringList)( l << "a" << "bc\r" << "def\r\r" << "ghij\r\r\r" );
150
    l.clear();
151
}
152
153
void tst_Q3Process::readLineStdout()
154
{
155
    QFETCH( QString, input );
156
157
    if (proc) delete proc;
158
    proc = new Q3Process( QString("cat/cat") );
159
    connect( proc, SIGNAL(processExited()),
160
	     SLOT(processExited()) );
161
162
    QVERIFY( proc->launch( input ) );
163
164
    QTestEventLoop::instance().enterLoop( 29 );
165
    if ( QTestEventLoop::instance().timeout() )
166
	QFAIL( "Operation timed out" );
167
168
    QTEST( linesReadStdout, "res" );
169
}
170
171
void tst_Q3Process::readLineStderr_data()
172
{
173
    readLineStdout_data();
174
}
175
176
void tst_Q3Process::readLineStderr()
177
{
178
    QFETCH( QString, input );
179
180
    if (proc) delete proc;
181
    proc = new Q3Process( QString("cat/cat -stderr").split(' ') );
182
    connect( proc, SIGNAL(processExited()),
183
	     SLOT(processExited()) );
184
185
    QVERIFY( proc->launch( input ) );
186
187
    QTestEventLoop::instance().enterLoop( 29 );
188
    if ( QTestEventLoop::instance().timeout() )
189
	QFAIL( "Operation timed out" );
190
191
    QTEST( linesReadStderr, "res" );
192
}
193
194
void tst_Q3Process::communication_data()
195
{
196
    QTest::addColumn<QStringList>("command");
197
    QTest::addColumn<int>("commFlags");
198
    QTest::addColumn<QString>("input");
199
    QTest::addColumn<QString>("resStdout");
200
    QTest::addColumn<QString>("resStderr");
201
202
    QTest::newRow( "no_dup_0" ) << QString("cat/cat").split(' ')
203
	<< ( Q3Process::Stdin | Q3Process::Stdout | Q3Process::Stderr )
204
	<< QString("12345")
205
	<< QString("12345")
206
	<< QString();
207
    QTest::newRow( "no_dup_1" ) << QString("cat/cat -stderr").split(' ')
208
	<< ( Q3Process::Stdin | Q3Process::Stdout | Q3Process::Stderr )
209
	<< QString("12345")
210
	<< QString()
211
	<< QString("12345");
212
    QTest::newRow( "no_dup_2" ) << QString("cat/cat -stdout_and_stderr").split(' ')
213
	<< ( Q3Process::Stdin | Q3Process::Stdout | Q3Process::Stderr )
214
	<< QString("12345")
215
	<< QString("12345")
216
	<< QString("23456");
217
218
    QTest::newRow( "dup_0" ) << QString("cat/cat").split(' ')
219
	<< ( Q3Process::Stdin | Q3Process::Stdout | Q3Process::Stderr | Q3Process::DupStderr )
220
	<< QString("12345")
221
	<< QString("12345")
222
	<< QString();
223
    QTest::newRow( "dup_1" ) << QString("cat/cat -stderr").split(' ')
224
	<< ( Q3Process::Stdin | Q3Process::Stdout | Q3Process::Stderr | Q3Process::DupStderr )
225
	<< QString("12345")
226
	<< QString("12345")
227
	<< QString();
228
    QTest::newRow( "dup_2" ) << QString("cat/cat -stdout_and_stderr").split(' ')
229
	<< ( Q3Process::Stdin | Q3Process::Stdout | Q3Process::Stderr | Q3Process::DupStderr )
230
	<< QString("12345")
231
	<< QString("1223344556")
232
	<< QString();
233
}
234
235
void tst_Q3Process::communication()
236
{
237
    for ( int i=0; i<2; i++ ) {
238
	cleanup();
239
240
	QFETCH( QStringList, command );
241
	QFETCH( int, commFlags );
242
	QFETCH( QString, input );
243
244
        if (proc) delete proc;
245
	proc = new Q3Process( command );
246
	proc->setCommunication( commFlags );
247
	connect( proc, SIGNAL(processExited()),
248
		SLOT(processExited()) );
249
250
	QVERIFY( proc->launch( input ) );
251
252
	QTestEventLoop::instance().enterLoop( 29 );
253
	if ( QTestEventLoop::instance().timeout() )
254
	    QFAIL( "Operation timed out" );
255
256
	if ( i == 0 ) {
257
	    QTEST( QString( proc->readStdout() ), "resStdout" );
258
	    QTEST( QString( proc->readStderr() ), "resStderr" );
259
	} else {
260
	    QTEST( QString( proc->readStdout() ), "resStdout" );
261
	    QTEST( QString( proc->readStderr() ), "resStderr" );
262
	}
263
    }
264
}
265
266
void tst_Q3Process::canReadLineStdout_data()
267
{
268
    readLineStdout_data();
269
}
270
271
void tst_Q3Process::canReadLineStdout()
272
{
273
    // This function tests the busy-loop abilities of the canReadLineStdout()
274
    // function.
275
    QFETCH( QString, input );
276
    QFETCH(QStringList, res);
277
278
    if (proc) delete proc;
279
    proc = new Q3Process( QString("cat/cat") );
280
    QVERIFY( proc->start() );
281
    proc->writeToStdin( input );
282
    proc->flushStdin();
283
    proc->closeStdin();
284
285
    do {
286
        connect(proc, SIGNAL(readyReadStdout()), this, SLOT(exitLoopSlot()));
287
        QTestEventLoop::instance().enterLoop(5);
288
        if (QTestEventLoop::instance().timeout()) {
289
            if (!proc->isRunning())
290
                break;
291
            QFAIL("Timed out while waiting for my kids");
292
        }
293
294
        // q3process can (actually!) emit readyRead() when
295
        // canReadLineStdout() is called.
296
        proc->disconnect();
297
298
        while ( proc->canReadLineStdout() )
299
            linesReadStdout << proc->readLineStdout();
300
    } while (linesReadStdout.size() < res.size() && proc->isRunning());
301
302
    // q3process can (actually!) emit readyRead() when
303
    // canReadLineStdout() is called.
304
    proc->disconnect();
305
306
    // if the last line is not terminated with a newline, we get it only after
307
    // we determined that the process is not running anymore
308
    if ( proc->canReadLineStdout() )
309
        linesReadStdout << proc->readLineStdout();
310
311
    QCOMPARE( linesReadStdout, res );
312
}
313
314
void tst_Q3Process::exitLoopSlot()
315
{
316
    QTestEventLoop::instance().exitLoop();
317
}
318
319
void tst_Q3Process::canReadLineStderr_data()
320
{
321
    readLineStdout_data();
322
}
323
324
void tst_Q3Process::canReadLineStderr()
325
{
326
    // This function tests the busy-loop abilities of the canReadLineStderr()
327
    // function.
328
    QFETCH( QString, input );
329
    QFETCH(QStringList, res);
330
331
    if (proc) delete proc;
332
    proc = new Q3Process( QString("cat/cat -stderr").split(' ') );
333
    QVERIFY( proc->start() );
334
    proc->writeToStdin( input );
335
    proc->flushStdin();
336
    proc->closeStdin();
337
338
    do {
339
        connect(proc, SIGNAL(readyReadStderr()), this, SLOT(exitLoopSlot()));
340
        QTestEventLoop::instance().enterLoop(5);
341
        if (QTestEventLoop::instance().timeout()) {
342
            if (!proc->isRunning())
343
                break;
344
            QFAIL("Timed out while waiting for my kids");
345
        }
346
347
        // q3process can (actually!) emit readyRead() when
348
        // canReadLineStdout() is called.
349
        proc->disconnect();
350
351
        while ( proc->canReadLineStderr() )
352
            linesReadStderr << proc->readLineStderr();
353
    } while (linesReadStderr.size() < res.size() && proc->isRunning());
354
355
    // q3process can (actually!) emit readyRead() when
356
    // canReadLineStdout() is called.
357
    proc->disconnect();
358
359
    // if the last line is not terminated with a newline, we get it only after
360
    // we determined that the process is not running anymore
361
    if ( proc->canReadLineStderr() )
362
	linesReadStderr << proc->readLineStderr();
363
364
    QCOMPARE( linesReadStderr, res );
365
}
366
367
void tst_Q3Process::processExited()
368
{
369
    if ( QTest::currentTestFunction() == QLatin1String("readLineStdout") ) {
370
	QVERIFY( proc != 0 );
371
372
        // q3process can (actually!) emit readyRead() when
373
        // canReadLineStdout() is called.
374
        proc->disconnect();
375
376
        while ( proc->canReadLineStdout() )
377
	    linesReadStdout << proc->readLineStdout();
378
379
	// if canReadLine...() returns FALSE, the readLine...() function should
380
	// return QString::null
381
	QVERIFY( proc->readLineStdout().isNull() );
382
383
	QTestEventLoop::instance().exitLoop();
384
385
    } else if ( QTest::currentTestFunction() == QLatin1String("readLineStderr") ) {
386
	QVERIFY( proc != 0 );
387
388
        // q3process can (actually!) emit readyRead() when
389
        // canReadLineStdout() is called.
390
        proc->disconnect();
391
392
        while ( proc->canReadLineStderr() )
393
	    linesReadStderr << proc->readLineStderr();
394
395
	// if canReadLine...() returns FALSE, the readLine...() function should
396
	// return QString::null
397
	QVERIFY( proc->readLineStderr().isNull() );
398
399
	QTestEventLoop::instance().exitLoop();
400
    } else if ( QTest::currentTestFunction() == QLatin1String("communication") ) {
401
	QTestEventLoop::instance().exitLoop();
402
    }
403
}
404
405
void tst_Q3Process::startWithNoEnvironment()
406
{
407
    QStringList args;
408
    QByteArray result;
409
#ifdef Q_OS_MACX
410
    args << "./echo/echo.app";
411
    result = "./echo/echo.app/Contents/MacOS/echo";
412
#elif defined Q_OS_WIN
413
    args << "./echo/echo";
414
    result = "echo";
415
#else
416
    args << "./echo/echo";
417
    result = args[0];
418
#endif
419
    args << "foo";
420
    proc = new Q3Process(args);
421
    QVERIFY(proc->start(/* environment = */ 0));
422
    connect(proc, SIGNAL(readyReadStdout()), this, SLOT(exitLoopSlot()));
423
424
    QTestEventLoop::instance().enterLoop(10);
425
    QVERIFY(!QTestEventLoop::instance().timeout());
426
427
#ifdef Q_OS_WIN
428
    // on different windows compilers the first arg is different, 
429
    // some just pass what was passed to createprocess while others 
430
    // expand the entire path.
431
    QVERIFY(proc->readStdout().contains(result));
432
#else
433
    QCOMPARE(proc->readStdout(), result);
434
#endif
435
}
436
437
void tst_Q3Process::startWithEmptyStringArgument()
438
{
439
    // Test that this doesn't assert (task 122353)
440
    Q3Process process("cmd");
441
    process.addArgument(QString());
442
443
    QStringList env;
444
    process.start(&env);
445
}
446
447
QTEST_MAIN(tst_Q3Process)
448
#include "tst_q3process.moc"