76 |
76 |
77 void oldCacheVersionFile_data(); |
77 void oldCacheVersionFile_data(); |
78 void oldCacheVersionFile(); |
78 void oldCacheVersionFile(); |
79 |
79 |
80 void sync(); |
80 void sync(); |
|
81 |
|
82 void crashWhenParentingCache(); |
|
83 }; |
|
84 |
|
85 // FIXME same as in tst_qnetworkreply.cpp .. could be unified |
|
86 // Does not work for POST/PUT! |
|
87 class MiniHttpServer: public QTcpServer |
|
88 { |
|
89 Q_OBJECT |
|
90 public: |
|
91 QTcpSocket *client; // always the last one that was received |
|
92 QByteArray dataToTransmit; |
|
93 QByteArray receivedData; |
|
94 bool doClose; |
|
95 bool multiple; |
|
96 int totalConnections; |
|
97 |
|
98 MiniHttpServer(const QByteArray &data) : client(0), dataToTransmit(data), doClose(true), multiple(false), totalConnections(0) |
|
99 { |
|
100 listen(); |
|
101 connect(this, SIGNAL(newConnection()), this, SLOT(doAccept())); |
|
102 } |
|
103 |
|
104 public slots: |
|
105 void doAccept() |
|
106 { |
|
107 client = nextPendingConnection(); |
|
108 client->setParent(this); |
|
109 ++totalConnections; |
|
110 connect(client, SIGNAL(readyRead()), this, SLOT(readyReadSlot())); |
|
111 } |
|
112 |
|
113 void readyReadSlot() |
|
114 { |
|
115 receivedData += client->readAll(); |
|
116 int doubleEndlPos = receivedData.indexOf("\r\n\r\n"); |
|
117 |
|
118 if (doubleEndlPos != -1) { |
|
119 // multiple requests incoming. remove the bytes of the current one |
|
120 if (multiple) |
|
121 receivedData.remove(0, doubleEndlPos+4); |
|
122 |
|
123 client->write(dataToTransmit); |
|
124 if (doClose) { |
|
125 client->disconnectFromHost(); |
|
126 disconnect(client, 0, this, 0); |
|
127 client = 0; |
|
128 } |
|
129 } |
|
130 } |
81 }; |
131 }; |
82 |
132 |
83 // Subclass that exposes the protected functions. |
133 // Subclass that exposes the protected functions. |
84 class SubQNetworkDiskCache : public QNetworkDiskCache |
134 class SubQNetworkDiskCache : public QNetworkDiskCache |
85 { |
135 { |
579 QDateTime dt; |
629 QDateTime dt; |
580 bool write; |
630 bool write; |
581 Runner *other; |
631 Runner *other; |
582 }; |
632 }; |
583 |
633 |
|
634 void tst_QNetworkDiskCache::crashWhenParentingCache() |
|
635 { |
|
636 // the trick here is to not send the complete response |
|
637 // but some data. So we get a readyRead() and it gets tried |
|
638 // to be saved to the cache |
|
639 QByteArray data("HTTP/1.0 200 OK\r\nCache-Control: max-age=300\r\nAge: 1\r\nContent-Length: 5\r\n\r\n123"); |
|
640 MiniHttpServer server(data); |
|
641 |
|
642 QNetworkAccessManager *manager = new QNetworkAccessManager(); |
|
643 QNetworkDiskCache *diskCache = new QNetworkDiskCache(manager); // parent to qnam! |
|
644 // we expect the temp dir to be cleaned at some point anyway |
|
645 diskCache->setCacheDirectory(QString("%1/cacheDir_%2").arg(QDir::tempPath()).arg(QCoreApplication::applicationPid())); |
|
646 manager->setCache(diskCache); |
|
647 |
|
648 QUrl url("http://127.0.0.1:" + QString::number(server.serverPort())); |
|
649 QNetworkRequest request(url); |
|
650 // request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork); |
|
651 QNetworkReply *reply = manager->get(request); // new reply is parented to qnam |
|
652 |
|
653 // wait for readyRead of reply! |
|
654 connect(reply, SIGNAL(readyRead()), &QTestEventLoop::instance(), SLOT(exitLoop())); |
|
655 QTestEventLoop::instance().enterLoop(5); |
|
656 QVERIFY(!QTestEventLoop::instance().timeout()); |
|
657 |
|
658 delete manager; // crashed before.. |
|
659 } |
|
660 |
584 void tst_QNetworkDiskCache::sync() |
661 void tst_QNetworkDiskCache::sync() |
585 { |
662 { |
586 // This tests would be a nice to have, but is currently not supported. |
663 // This tests would be a nice to have, but is currently not supported. |
587 return; |
664 return; |
588 |
665 |