| 1 | /**************************************************************************** |
| 2 | ** |
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. |
| 4 | ** Contact: https://www.qt.io/licensing/ |
| 5 | ** |
| 6 | ** This file is part of the test suite of the Qt Toolkit. |
| 7 | ** |
| 8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
| 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 The Qt Company. For licensing terms |
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
| 15 | ** information use the contact form at https://www.qt.io/contact-us. |
| 16 | ** |
| 17 | ** GNU General Public License Usage |
| 18 | ** Alternatively, this file may be used under the terms of the GNU |
| 19 | ** General Public License version 3 as published by the Free Software |
| 20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
| 21 | ** included in the packaging of this file. Please review the following |
| 22 | ** information to ensure the GNU General Public License requirements will |
| 23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| 24 | ** |
| 25 | ** $QT_END_LICENSE$ |
| 26 | ** |
| 27 | ****************************************************************************/ |
| 28 | |
| 29 | #include <QtCore/QTemporaryDir> |
| 30 | #include <QtTest/QtTest> |
| 31 | #include <QtGui/qevent.h> |
| 32 | |
| 33 | class tst_qfileopenevent : public QObject |
| 34 | { |
| 35 | Q_OBJECT |
| 36 | public: |
| 37 | tst_qfileopenevent(){} |
| 38 | ~tst_qfileopenevent(); |
| 39 | |
| 40 | public slots: |
| 41 | void initTestCase(); |
| 42 | void cleanupTestCase(); |
| 43 | |
| 44 | private slots: |
| 45 | void constructor(); |
| 46 | void fileOpen(); |
| 47 | void handleLifetime(); |
| 48 | void multiOpen(); |
| 49 | void sendAndReceive(); |
| 50 | |
| 51 | private: |
| 52 | void createFile(const QString &filename, const QByteArray &content); |
| 53 | QFileOpenEvent * createFileAndEvent(const QString &filename, const QByteArray &content); |
| 54 | void checkReadAndWrite(QFileOpenEvent& event, const QByteArray& readContent, const QByteArray& writeContent, bool writeOk); |
| 55 | QByteArray readFileContent(QFileOpenEvent& event); |
| 56 | bool appendFileContent(QFileOpenEvent& event, const QByteArray& writeContent); |
| 57 | |
| 58 | bool event(QEvent *); |
| 59 | |
| 60 | QTemporaryDir m_temporaryDir; |
| 61 | QString m_originalCurrent; |
| 62 | }; |
| 63 | |
| 64 | tst_qfileopenevent::~tst_qfileopenevent() |
| 65 | { |
| 66 | }; |
| 67 | |
| 68 | void tst_qfileopenevent::initTestCase() |
| 69 | { |
| 70 | m_originalCurrent = QDir::currentPath(); |
| 71 | QDir::setCurrent(m_temporaryDir.path()); |
| 72 | } |
| 73 | |
| 74 | void tst_qfileopenevent::cleanupTestCase() |
| 75 | { |
| 76 | QDir::setCurrent(m_originalCurrent); |
| 77 | } |
| 78 | |
| 79 | void tst_qfileopenevent::createFile(const QString &filename, const QByteArray &content) |
| 80 | { |
| 81 | QFile file(filename); |
| 82 | file.open(flags: QFile::WriteOnly); |
| 83 | file.write(data: content); |
| 84 | file.close(); |
| 85 | } |
| 86 | |
| 87 | QFileOpenEvent * tst_qfileopenevent::createFileAndEvent(const QString &filename, const QByteArray &content) |
| 88 | { |
| 89 | createFile(filename, content); |
| 90 | return new QFileOpenEvent(filename); |
| 91 | } |
| 92 | |
| 93 | void tst_qfileopenevent::constructor() |
| 94 | { |
| 95 | // check that filename get/set works |
| 96 | QFileOpenEvent nameTest(QLatin1String("fileNameTest" )); |
| 97 | QCOMPARE(nameTest.file(), QLatin1String("fileNameTest" )); |
| 98 | |
| 99 | // check that url get/set works |
| 100 | QFileOpenEvent urlTest(QUrl(QLatin1String("file:///urlNameTest" ))); |
| 101 | QCOMPARE(urlTest.url().toString(), QLatin1String("file:///urlNameTest" )); |
| 102 | } |
| 103 | |
| 104 | QByteArray tst_qfileopenevent::readFileContent(QFileOpenEvent& event) |
| 105 | { |
| 106 | QFile file; |
| 107 | event.openFile(file, flags: QFile::ReadOnly); |
| 108 | file.seek(offset: 0); |
| 109 | QByteArray data = file.readAll(); |
| 110 | return data; |
| 111 | } |
| 112 | |
| 113 | bool tst_qfileopenevent::appendFileContent(QFileOpenEvent& event, const QByteArray& writeContent) |
| 114 | { |
| 115 | QFile file; |
| 116 | bool ok = event.openFile(file, flags: QFile::Append | QFile::Unbuffered); |
| 117 | if (ok) |
| 118 | ok = file.write(data: writeContent) == writeContent.size(); |
| 119 | return ok; |
| 120 | } |
| 121 | |
| 122 | void tst_qfileopenevent::checkReadAndWrite(QFileOpenEvent& event, const QByteArray& readContent, const QByteArray& writeContent, bool writeOk) |
| 123 | { |
| 124 | QCOMPARE(readFileContent(event), readContent); |
| 125 | QCOMPARE(appendFileContent(event, writeContent), writeOk); |
| 126 | QCOMPARE(readFileContent(event), writeOk ? readContent+writeContent : readContent); |
| 127 | } |
| 128 | |
| 129 | void tst_qfileopenevent::fileOpen() |
| 130 | { |
| 131 | createFile(filename: QLatin1String("testFileOpen" ), content: QByteArray("test content+RFileWrite" )); |
| 132 | |
| 133 | // filename event |
| 134 | QUrl fileUrl; // need to get the URL during the file test, for use in the URL test |
| 135 | { |
| 136 | QFileOpenEvent nameTest(QLatin1String("testFileOpen" )); |
| 137 | fileUrl = nameTest.url(); |
| 138 | checkReadAndWrite(event&: nameTest, readContent: QByteArray("test content+RFileWrite" ), writeContent: QByteArray("+nameWrite" ), writeOk: true); |
| 139 | } |
| 140 | |
| 141 | // url event |
| 142 | { |
| 143 | QFileOpenEvent urlTest(fileUrl); |
| 144 | checkReadAndWrite(event&: urlTest, readContent: QByteArray("test content+RFileWrite+nameWrite" ), writeContent: QByteArray("+urlWrite" ), writeOk: true); |
| 145 | } |
| 146 | |
| 147 | QFile::remove(fileName: QLatin1String("testFileOpen" )); |
| 148 | } |
| 149 | |
| 150 | void tst_qfileopenevent::handleLifetime() |
| 151 | { |
| 152 | QScopedPointer<QFileOpenEvent> event(createFileAndEvent(filename: QLatin1String("testHandleLifetime" ), content: QByteArray("test content" ))); |
| 153 | |
| 154 | // open a QFile after the original RFile is closed |
| 155 | QFile qFile; |
| 156 | QCOMPARE(event->openFile(qFile, QFile::Append | QFile::Unbuffered), true); |
| 157 | event.reset(other: 0); |
| 158 | |
| 159 | // write to the QFile after the event is closed |
| 160 | QString writeContent(QLatin1String("+closed original handles" )); |
| 161 | QCOMPARE(int(qFile.write(writeContent.toUtf8())), writeContent.size()); |
| 162 | qFile.close(); |
| 163 | |
| 164 | // check the content |
| 165 | QFile checkContent("testHandleLifetime" ); |
| 166 | checkContent.open(flags: QFile::ReadOnly); |
| 167 | QString content(checkContent.readAll()); |
| 168 | QCOMPARE(content, QLatin1String("test content+closed original handles" )); |
| 169 | checkContent.close(); |
| 170 | |
| 171 | QFile::remove(fileName: QLatin1String("testHandleLifetime" )); |
| 172 | } |
| 173 | |
| 174 | void tst_qfileopenevent::multiOpen() |
| 175 | { |
| 176 | QScopedPointer<QFileOpenEvent> event(createFileAndEvent(filename: QLatin1String("testMultiOpen" ), content: QByteArray("itlum" ))); |
| 177 | |
| 178 | QFile files[5]; |
| 179 | for (int i=0; i<5; i++) { |
| 180 | QCOMPARE(event->openFile(files[i], QFile::ReadOnly), true); |
| 181 | } |
| 182 | for (int i=0; i<5; i++) |
| 183 | files[i].seek(offset: i); |
| 184 | QString str; |
| 185 | for (int i=4; i>=0; i--) { |
| 186 | char c; |
| 187 | files[i].getChar(c: &c); |
| 188 | str.append(c); |
| 189 | files[i].close(); |
| 190 | } |
| 191 | QCOMPARE(str, QLatin1String("multi" )); |
| 192 | |
| 193 | QFile::remove(fileName: QLatin1String("testMultiOpen" )); |
| 194 | } |
| 195 | |
| 196 | bool tst_qfileopenevent::event(QEvent *event) |
| 197 | { |
| 198 | if (event->type() != QEvent::FileOpen) |
| 199 | return QObject::event(event); |
| 200 | QFileOpenEvent* fileOpenEvent = static_cast<QFileOpenEvent *>(event); |
| 201 | appendFileContent(event&: *fileOpenEvent, writeContent: "+received" ); |
| 202 | return true; |
| 203 | } |
| 204 | |
| 205 | void tst_qfileopenevent::sendAndReceive() |
| 206 | { |
| 207 | QScopedPointer<QFileOpenEvent> event(createFileAndEvent(filename: QLatin1String("testSendAndReceive" ), content: QByteArray("sending" ))); |
| 208 | |
| 209 | QCoreApplication::instance()->postEvent(receiver: this, event: event.take()); |
| 210 | QCoreApplication::instance()->processEvents(); |
| 211 | |
| 212 | // QTBUG-17468: On Mac, processEvents doesn't always process posted events |
| 213 | QCoreApplication::instance()->sendPostedEvents(); |
| 214 | |
| 215 | // check the content |
| 216 | QFile checkContent("testSendAndReceive" ); |
| 217 | QCOMPARE(checkContent.open(QFile::ReadOnly), true); |
| 218 | QString content(checkContent.readAll()); |
| 219 | QCOMPARE(content, QLatin1String("sending+received" )); |
| 220 | checkContent.close(); |
| 221 | |
| 222 | QFile::remove(fileName: QLatin1String("testSendAndReceive" )); |
| 223 | } |
| 224 | |
| 225 | QTEST_MAIN(tst_qfileopenevent) |
| 226 | #include "tst_qfileopenevent.moc" |
| 227 | |