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
#include <QtNetwork/QtNetwork>
45
#include "../../shared/util.h"
46
#include "../network-settings.h"
47
48
#ifndef QT_NO_BEARERMANAGEMENT
49
#include <QtNetwork/qnetworkconfigmanager.h>
50
#include <QtNetwork/qnetworkconfiguration.h>
51
#include <QtNetwork/qnetworksession.h>
52
#endif
53
54
#define TESTFILE QString("http://%1/qtest/cgi-bin/").arg(QtNetworkSettings::serverName())
55
56
class tst_QAbstractNetworkCache : public QObject
57
{
58
    Q_OBJECT
59
60
public:
61
    tst_QAbstractNetworkCache();
62
    virtual ~tst_QAbstractNetworkCache();
63
64
private slots:
65
    void initTestCase();
66
    void expires_data();
67
    void expires();
68
    void expiresSynchronous_data();
69
    void expiresSynchronous();
70
71
    void lastModified_data();
72
    void lastModified();
73
    void lastModifiedSynchronous_data();
74
    void lastModifiedSynchronous();
75
76
    void etag_data();
77
    void etag();
78
    void etagSynchronous_data();
79
    void etagSynchronous();
80
81
    void cacheControl_data();
82
    void cacheControl();
83
    void cacheControlSynchronous_data();
84
    void cacheControlSynchronous();
85
86
    void deleteCache();
87
88
private:
89
    void check();
90
    void checkSynchronous();
91
92
#ifndef QT_NO_BEARERMANAGEMENT
93
    QNetworkConfigurationManager *netConfMan;
94
    QNetworkConfiguration networkConfiguration;
95
    QScopedPointer<QNetworkSession> networkSession;
96
#endif
97
};
98
99
class NetworkDiskCache : public QNetworkDiskCache
100
{
101
    Q_OBJECT
102
public:
103
    NetworkDiskCache(QObject *parent = 0)
104
        : QNetworkDiskCache(parent)
105
        , gotData(false)
106
    {
107
        QString location = QDir::tempPath() + QLatin1String("/tst_qnetworkdiskcache/");
108
        setCacheDirectory(location);
109
        clear();
110
    }
111
112
    QIODevice *data(const QUrl &url)
113
    {
114
        gotData = true;
115
        return QNetworkDiskCache::data(url);
116
    }
117
118
    bool gotData;
119
};
120
121
122
tst_QAbstractNetworkCache::tst_QAbstractNetworkCache()
123
{
124
    Q_SET_DEFAULT_IAP
125
126
    QCoreApplication::setOrganizationName(QLatin1String("Trolltech"));
127
    QCoreApplication::setApplicationName(QLatin1String("autotest_qabstractnetworkcache"));
128
    QCoreApplication::setApplicationVersion(QLatin1String("1.0"));
129
}
130
131
tst_QAbstractNetworkCache::~tst_QAbstractNetworkCache()
132
{
133
}
134
135
static bool AlwaysTrue = true;
136
static bool AlwaysFalse = false;
137
138
Q_DECLARE_METATYPE(QNetworkRequest::CacheLoadControl)
139
140
void tst_QAbstractNetworkCache::initTestCase()
141
{
142
#ifndef QT_NO_BEARERMANAGEMENT
143
    netConfMan = new QNetworkConfigurationManager(this);
144
    netConfMan->updateConfigurations();
145
    connect(netConfMan, SIGNAL(updateCompleted()), &QTestEventLoop::instance(), SLOT(exitLoop()));
146
    QTestEventLoop::instance().enterLoop(10);
147
    networkConfiguration = netConfMan->defaultConfiguration();
148
    if (networkConfiguration.isValid()) {
149
        networkSession.reset(new QNetworkSession(networkConfiguration));
150
        if (!networkSession->isOpen()) {
151
            networkSession->open();
152
            QVERIFY(networkSession->waitForOpened(30000));
153
        }
154
    } else {
155
        QVERIFY(!(netConfMan->capabilities() & QNetworkConfigurationManager::NetworkSessionRequired));
156
    }
157
#endif
158
}
159
160
void tst_QAbstractNetworkCache::expires_data()
161
{
162
    QTest::addColumn<QNetworkRequest::CacheLoadControl>("cacheLoadControl");
163
    QTest::addColumn<QString>("url");
164
    QTest::addColumn<bool>("fetchFromCache");
165
166
    QTest::newRow("304-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_expires304.cgi" << AlwaysFalse;
167
    QTest::newRow("304-1") << QNetworkRequest::PreferNetwork << "httpcachetest_expires304.cgi" << true;
168
    QTest::newRow("304-2") << QNetworkRequest::AlwaysCache << "httpcachetest_expires304.cgi" << AlwaysTrue;
169
    QTest::newRow("304-3") << QNetworkRequest::PreferCache << "httpcachetest_expires304.cgi" << true;
170
171
    QTest::newRow("500-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_expires500.cgi" << AlwaysFalse;
172
    QTest::newRow("500-1") << QNetworkRequest::PreferNetwork << "httpcachetest_expires500.cgi" << true;
173
    QTest::newRow("500-2") << QNetworkRequest::AlwaysCache << "httpcachetest_expires500.cgi" << AlwaysTrue;
174
    QTest::newRow("500-3") << QNetworkRequest::PreferCache << "httpcachetest_expires500.cgi" << true;
175
176
    QTest::newRow("200-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_expires200.cgi" << AlwaysFalse;
177
    QTest::newRow("200-1") << QNetworkRequest::PreferNetwork << "httpcachetest_expires200.cgi" << false;
178
    QTest::newRow("200-2") << QNetworkRequest::AlwaysCache << "httpcachetest_expires200.cgi" << AlwaysTrue;
179
    QTest::newRow("200-3") << QNetworkRequest::PreferCache << "httpcachetest_expires200.cgi" << false;
180
}
181
182
void tst_QAbstractNetworkCache::expires()
183
{
184
    check();
185
}
186
187
void tst_QAbstractNetworkCache::expiresSynchronous_data()
188
{
189
    expires_data();
190
}
191
192
void tst_QAbstractNetworkCache::expiresSynchronous()
193
{
194
    checkSynchronous();
195
}
196
197
void tst_QAbstractNetworkCache::lastModified_data()
198
{
199
    QTest::addColumn<QNetworkRequest::CacheLoadControl>("cacheLoadControl");
200
    QTest::addColumn<QString>("url");
201
    QTest::addColumn<bool>("fetchFromCache");
202
203
    QTest::newRow("304-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_lastModified304.cgi" << AlwaysFalse;
204
    QTest::newRow("304-1") << QNetworkRequest::PreferNetwork << "httpcachetest_lastModified304.cgi" << true;
205
    QTest::newRow("304-2") << QNetworkRequest::AlwaysCache << "httpcachetest_lastModified304.cgi" << AlwaysTrue;
206
    QTest::newRow("304-3") << QNetworkRequest::PreferCache << "httpcachetest_lastModified304.cgi" << true;
207
208
    QTest::newRow("200-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_lastModified200.cgi" << AlwaysFalse;
209
    QTest::newRow("200-1") << QNetworkRequest::PreferNetwork << "httpcachetest_lastModified200.cgi" << false;
210
    QTest::newRow("200-2") << QNetworkRequest::AlwaysCache << "httpcachetest_lastModified200.cgi" << AlwaysTrue;
211
    QTest::newRow("200-3") << QNetworkRequest::PreferCache << "httpcachetest_lastModified200.cgi" << false;
212
}
213
214
void tst_QAbstractNetworkCache::lastModified()
215
{
216
    check();
217
}
218
219
void tst_QAbstractNetworkCache::lastModifiedSynchronous_data()
220
{
221
    tst_QAbstractNetworkCache::lastModified_data();
222
}
223
224
void tst_QAbstractNetworkCache::lastModifiedSynchronous()
225
{
226
    checkSynchronous();
227
}
228
229
void tst_QAbstractNetworkCache::etag_data()
230
{
231
    QTest::addColumn<QNetworkRequest::CacheLoadControl>("cacheLoadControl");
232
    QTest::addColumn<QString>("url");
233
    QTest::addColumn<bool>("fetchFromCache");
234
235
    QTest::newRow("304-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_etag304.cgi" << AlwaysFalse;
236
    QTest::newRow("304-1") << QNetworkRequest::PreferNetwork << "httpcachetest_etag304.cgi" << true;
237
    QTest::newRow("304-2") << QNetworkRequest::AlwaysCache << "httpcachetest_etag304.cgi" << AlwaysTrue;
238
    QTest::newRow("304-3") << QNetworkRequest::PreferCache << "httpcachetest_etag304.cgi" << true;
239
240
    QTest::newRow("200-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_etag200.cgi" << AlwaysFalse;
241
    QTest::newRow("200-1") << QNetworkRequest::PreferNetwork << "httpcachetest_etag200.cgi" << false;
242
    QTest::newRow("200-2") << QNetworkRequest::AlwaysCache << "httpcachetest_etag200.cgi" << AlwaysTrue;
243
    QTest::newRow("200-3") << QNetworkRequest::PreferCache << "httpcachetest_etag200.cgi" << false;
244
}
245
246
void tst_QAbstractNetworkCache::etag()
247
{
248
    check();
249
}
250
251
void tst_QAbstractNetworkCache::etagSynchronous_data()
252
{
253
    tst_QAbstractNetworkCache::etag_data();
254
}
255
256
void tst_QAbstractNetworkCache::etagSynchronous()
257
{
258
    checkSynchronous();
259
}
260
261
void tst_QAbstractNetworkCache::cacheControl_data()
262
{
263
    QTest::addColumn<QNetworkRequest::CacheLoadControl>("cacheLoadControl");
264
    QTest::addColumn<QString>("url");
265
    QTest::addColumn<bool>("fetchFromCache");
266
    QTest::newRow("200-0") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol.cgi?max-age=-1" << true;
267
    QTest::newRow("200-1") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol-expire.cgi" << false;
268
269
    QTest::newRow("200-2") << QNetworkRequest::AlwaysNetwork << "httpcachetest_cachecontrol.cgi?no-cache" << AlwaysFalse;
270
    QTest::newRow("200-3") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol.cgi?no-cache" << false;
271
    QTest::newRow("200-4") << QNetworkRequest::AlwaysCache << "httpcachetest_cachecontrol.cgi?no-cache" << false;
272
    QTest::newRow("200-5") << QNetworkRequest::PreferCache << "httpcachetest_cachecontrol.cgi?no-cache" << false;
273
274
    QTest::newRow("304-0") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol.cgi?max-age=1000" << true;
275
276
    QTest::newRow("304-1") << QNetworkRequest::AlwaysNetwork << "httpcachetest_cachecontrol.cgi?max-age=1000, must-revalidate" << AlwaysFalse;
277
    QTest::newRow("304-2") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol.cgi?max-age=1000, must-revalidate" << true;
278
    QTest::newRow("304-3") << QNetworkRequest::AlwaysCache << "httpcachetest_cachecontrol.cgi?max-age=1000, must-revalidate" << false;
279
    QTest::newRow("304-4") << QNetworkRequest::PreferCache << "httpcachetest_cachecontrol.cgi?max-age=1000, must-revalidate" << true;
280
281
    // see QTBUG-7060
282
    //QTest::newRow("nokia-boston") << QNetworkRequest::PreferNetwork << "http://waplabdc.nokia-boston.com/browser/users/venkat/cache/Cache_directives/private_1b.asp" << true;
283
    QTest::newRow("304-2b") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol200.cgi?private, max-age=1000" << true;
284
    QTest::newRow("304-4b") << QNetworkRequest::PreferCache << "httpcachetest_cachecontrol200.cgi?private, max-age=1000" << true;
285
}
286
287
void tst_QAbstractNetworkCache::cacheControl()
288
{
289
    check();
290
}
291
292
void tst_QAbstractNetworkCache::cacheControlSynchronous_data()
293
{
294
    tst_QAbstractNetworkCache::cacheControl_data();
295
}
296
297
void tst_QAbstractNetworkCache::cacheControlSynchronous()
298
{
299
    checkSynchronous();
300
}
301
302
void tst_QAbstractNetworkCache::check()
303
{
304
    QFETCH(QNetworkRequest::CacheLoadControl, cacheLoadControl);
305
    QFETCH(QString, url);
306
    QFETCH(bool, fetchFromCache);
307
308
    QNetworkAccessManager manager;
309
    NetworkDiskCache *diskCache = new NetworkDiskCache(&manager);
310
    manager.setCache(diskCache);
311
    QCOMPARE(diskCache->gotData, false);
312
313
    QUrl realUrl = url.contains("://") ? url : TESTFILE + url;
314
    QNetworkRequest request(realUrl);
315
316
    // prime the cache
317
    QNetworkReply *reply = manager.get(request);
318
    QSignalSpy downloaded1(reply, SIGNAL(finished()));
319
    QTRY_COMPARE(downloaded1.count(), 1);
320
    QCOMPARE(diskCache->gotData, false);
321
    QByteArray goodData = reply->readAll();
322
323
    request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, cacheLoadControl);
324
325
    // should be in the cache now
326
    QNetworkReply *reply2 = manager.get(request);
327
    QSignalSpy downloaded2(reply2, SIGNAL(finished()));
328
    QTRY_COMPARE(downloaded2.count(), 1);
329
330
    QByteArray secondData = reply2->readAll();
331
    if (!fetchFromCache && cacheLoadControl == QNetworkRequest::AlwaysCache) {
332
        QCOMPARE(reply2->error(), QNetworkReply::ContentNotFoundError);
333
        QCOMPARE(secondData, QByteArray());
334
    } else {
335
        QCOMPARE(reply2->error(), QNetworkReply::NoError);
336
        QCOMPARE(QString(secondData), QString(goodData));
337
        QCOMPARE(secondData, goodData);
338
        QCOMPARE(reply2->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
339
    }
340
341
    if (fetchFromCache) {
342
        QList<QByteArray> rawHeaderList = reply->rawHeaderList();
343
        QList<QByteArray> rawHeaderList2 = reply2->rawHeaderList();
344
        qSort(rawHeaderList);
345
        qSort(rawHeaderList2);
346
    }
347
    QCOMPARE(diskCache->gotData, fetchFromCache);
348
}
349
350
void tst_QAbstractNetworkCache::checkSynchronous()
351
{
352
    QSKIP("not working yet, see QTBUG-15221", SkipAll);
353
354
    QFETCH(QNetworkRequest::CacheLoadControl, cacheLoadControl);
355
    QFETCH(QString, url);
356
    QFETCH(bool, fetchFromCache);
357
358
    QNetworkAccessManager manager;
359
    NetworkDiskCache *diskCache = new NetworkDiskCache(&manager);
360
    manager.setCache(diskCache);
361
    QCOMPARE(diskCache->gotData, false);
362
363
    QUrl realUrl = url.contains("://") ? url : TESTFILE + url;
364
    QNetworkRequest request(realUrl);
365
366
    request.setAttribute(
367
            QNetworkRequest::SynchronousRequestAttribute,
368
            true);
369
370
    // prime the cache
371
    QNetworkReply *reply = manager.get(request);
372
    QVERIFY(reply->isFinished()); // synchronous
373
    QCOMPARE(diskCache->gotData, false);
374
    QByteArray goodData = reply->readAll();
375
376
    request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, cacheLoadControl);
377
378
    // should be in the cache now
379
    QNetworkReply *reply2 = manager.get(request);
380
    QVERIFY(reply2->isFinished()); // synchronous
381
382
    QByteArray secondData = reply2->readAll();
383
    if (!fetchFromCache && cacheLoadControl == QNetworkRequest::AlwaysCache) {
384
        QCOMPARE(reply2->error(), QNetworkReply::ContentNotFoundError);
385
        QCOMPARE(secondData, QByteArray());
386
    } else {
387
        if (reply2->error() != QNetworkReply::NoError)
388
            qDebug() << reply2->errorString();
389
        QCOMPARE(reply2->error(), QNetworkReply::NoError);
390
        QCOMPARE(QString(secondData), QString(goodData));
391
        QCOMPARE(secondData, goodData);
392
        QCOMPARE(reply2->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
393
    }
394
395
    if (fetchFromCache) {
396
        QList<QByteArray> rawHeaderList = reply->rawHeaderList();
397
        QList<QByteArray> rawHeaderList2 = reply2->rawHeaderList();
398
        qSort(rawHeaderList);
399
        qSort(rawHeaderList2);
400
    }
401
    QCOMPARE(diskCache->gotData, fetchFromCache);
402
}
403
404
void tst_QAbstractNetworkCache::deleteCache()
405
{
406
    QNetworkAccessManager manager;
407
    NetworkDiskCache *diskCache = new NetworkDiskCache(&manager);
408
    manager.setCache(diskCache);
409
410
    QString url = "httpcachetest_cachecontrol.cgi?max-age=1000";
411
    QNetworkRequest request(QUrl(TESTFILE + url));
412
    QNetworkReply *reply = manager.get(request);
413
    QSignalSpy downloaded1(reply, SIGNAL(finished()));
414
    manager.setCache(0);
415
    QTRY_COMPARE(downloaded1.count(), 1);
416
}
417
418
419
QTEST_MAIN(tst_QAbstractNetworkCache)
420
#include "tst_qabstractnetworkcache.moc"