1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
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 The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QtTest/QtTest>
44
45
46 #include <qfile.h>
47 #include <qdir.h>
48 #include <qcoreapplication.h>
49 #include <qlibrary.h>
50 #include <qtemporaryfile.h>
51 #include <qdir.h>
52 #include <qfileinfo.h>
53 #ifdef Q_OS_UNIX
54 #include <fcntl.h>
55 #include <unistd.h>
56 #include <sys/stat.h>
57 #include <sys/types.h>
58 #include <pwd.h>
59 #endif
60 #ifdef Q_OS_WIN
61 #define _WIN32_WINNT 0x500
62 #include <qt_windows.h>
63 #include <qlibrary.h>
64 #ifndef Q_OS_WINCE
65 #include <lm.h>
66 #endif
67 #endif
68 #include <qplatformdefs.h>
69 #include <qdebug.h>
70 #ifdef Q_OS_SYMBIAN
71 #include <f32file.h>
72 #include <private/qcore_symbian_p.h>
73 #endif
74 #include "../network-settings.h"
75 #include <private/qfileinfo_p.h>
76 #include "../../shared/filesystem.h"
77
78 #if defined(Q_OS_SYMBIAN)
79 # define NO_SYMLINKS
80 #endif
81
82 QT_BEGIN_NAMESPACE
83 extern Q_AUTOTEST_EXPORT bool qIsLikelyToBeNfs(int /* handle */);
84 QT_END_NAMESPACE
85
86 //TESTED_CLASS=
87 //TESTED_FILES=
88
89 class tst_QFileInfo : public QObject
90 {
91 Q_OBJECT
92
93 public:
94 tst_QFileInfo();
95 ~tst_QFileInfo();
96
97 private slots:
98 void getSetCheck();
99
100 void copy();
101
102 void isFile_data();
103 void isFile();
104
105 void isDir_data();
106 void isDir();
107
108 void isRoot_data();
109 void isRoot();
110
111 void exists_data();
112 void exists();
113
114 void absolutePath_data();
115 void absolutePath();
116
117 void absFilePath_data();
118 void absFilePath();
119
120 void canonicalPath();
121 void canonicalFilePath();
122
123 void fileName_data();
124 void fileName();
125
126 void bundleName_data();
127 void bundleName();
128
129 void dir_data();
130 void dir();
131
132 void suffix_data();
133 void suffix();
134
135 void completeSuffix_data();
136 void completeSuffix();
137
138 void baseName_data();
139 void baseName();
140
141 void completeBaseName_data();
142 void completeBaseName();
143
144 void permission_data();
145 void permission();
146
147 void size_data();
148 void size();
149
150 void systemFiles();
151
152 void compare_data();
153 void compare();
154
155 void consistent_data();
156 void consistent();
157
158 void fileTimes_data();
159 void fileTimes();
160 void fileTimes_oldFile();
161
162 void isSymLink_data();
163 void isSymLink();
164
165 void isHidden_data();
166 void isHidden();
167 #if defined(Q_OS_MAC)
168 void isHiddenFromFinder();
169 #endif
170
171 void isBundle_data();
172 void isBundle();
173
174 void isLocalFs_data();
175 void isLocalFs();
176
177 void refresh();
178
179 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
180 void ntfsJunctionPointsAndSymlinks_data();
181 void ntfsJunctionPointsAndSymlinks();
182 void brokenShortcut();
183 #endif
184
185 void isWritable();
186 void isExecutable();
187 void testDecomposedUnicodeNames_data();
188 void testDecomposedUnicodeNames();
189
190 void equalOperator() const;
191 void equalOperatorWithDifferentSlashes() const;
192 void notEqualOperator() const;
193
194 void detachingOperations();
195
196 #if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
197 void owner();
198 #endif
199 void group();
200
201 void invalidState();
202 };
203
tst_QFileInfo()204 tst_QFileInfo::tst_QFileInfo()
205 {
206 }
207
~tst_QFileInfo()208 tst_QFileInfo::~tst_QFileInfo()
209 {
210 QFile::remove("brokenlink.lnk");
211 QFile::remove("link.lnk");
212 QFile::remove("file1");
213 QFile::remove("dummyfile");
214 QFile::remove("simplefile.txt");
215 QFile::remove("longFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileName.txt");
216 #ifdef Q_OS_SYMBIAN
217 QFile::remove("hidden.txt");
218 QFile::remove("nothidden.txt");
219 #else
220 QFile::remove("tempfile.txt");
221 #endif
222
223 #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
224 QDir().rmdir("./.hidden-directory");
225 QFile::remove("link_to_tst_qfileinfo");
226 #endif
227 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
228 QDir().rmdir("./hidden-directory");
229 QDir().rmdir("abs_symlink");
230 QDir().rmdir("rel_symlink");
231 QDir().rmdir("junction_pwd");
232 QDir().rmdir("junction_root");
233 QDir().rmdir("mountpoint");
234 QFile::remove("abs_symlink.cpp");
235 QFile::remove("rel_symlink.cpp");
236 #endif
237 }
238
239 // Testing get/set functions
getSetCheck()240 void tst_QFileInfo::getSetCheck()
241 {
242 QFileInfo obj1;
243 // bool QFileInfo::caching()
244 // void QFileInfo::setCaching(bool)
245 obj1.setCaching(false);
246 QCOMPARE(false, obj1.caching());
247 obj1.setCaching(true);
248 QCOMPARE(true, obj1.caching());
249 }
250
getPrivate(QFileInfo & info)251 static QFileInfoPrivate* getPrivate(QFileInfo &info)
252 {
253 return (*reinterpret_cast<QFileInfoPrivate**>(&info));
254 }
255
copy()256 void tst_QFileInfo::copy()
257 {
258 QTemporaryFile t;
259 t.open();
260 QFileInfo info(t.fileName());
261 QVERIFY(info.exists());
262
263 //copy constructor
264 QFileInfo info2(info);
265 QFileInfoPrivate *privateInfo = getPrivate(info);
266 QFileInfoPrivate *privateInfo2 = getPrivate(info2);
267 QCOMPARE(privateInfo, privateInfo2);
268
269 //operator =
270 QFileInfo info3 = info;
271 QFileInfoPrivate *privateInfo3 = getPrivate(info3);
272 QCOMPARE(privateInfo, privateInfo3);
273 QCOMPARE(privateInfo2, privateInfo3);
274
275 //refreshing info3 will detach it
276 QFile file(info.absoluteFilePath());
277 QVERIFY(file.open(QFile::WriteOnly));
278 QCOMPARE(file.write("JAJAJAA"), qint64(7));
279 file.flush();
280
281 QTest::qWait(250);
282 #if defined(Q_OS_WIN) || defined(Q_OS_WINCE)
283 if (QSysInfo::windowsVersion() & QSysInfo::WV_VISTA ||
284 QSysInfo::windowsVersion() & QSysInfo::WV_CE_based)
285 file.close();
286 #endif
287 #if defined(Q_OS_WINCE)
288 // On Windows CE we need to close the file.
289 // Otherwise the content will be cached and not
290 // flushed to the storage, although we flushed it
291 // manually!!! CE has interim cache, we cannot influence.
292 QTest::qWait(5000);
293 #endif
294 info3.refresh();
295 privateInfo3 = getPrivate(info3);
296 QVERIFY(privateInfo != privateInfo3);
297 QVERIFY(privateInfo2 != privateInfo3);
298 QCOMPARE(privateInfo, privateInfo2);
299 }
300
isFile_data()301 void tst_QFileInfo::isFile_data()
302 {
303 QTest::addColumn<QString>("path");
304 QTest::addColumn<bool>("expected");
305
306 QTest::newRow("data0") << QDir::currentPath() << false;
307 QTest::newRow("data1") << SRCDIR "tst_qfileinfo.cpp" << true;
308 QTest::newRow("data2") << ":/tst_qfileinfo/resources/" << false;
309 QTest::newRow("data3") << ":/tst_qfileinfo/resources/file1" << true;
310 QTest::newRow("data4") << ":/tst_qfileinfo/resources/afilethatshouldnotexist" << false;
311 }
312
isFile()313 void tst_QFileInfo::isFile()
314 {
315 QFETCH(QString, path);
316 QFETCH(bool, expected);
317
318 QFileInfo fi(path);
319 QCOMPARE(fi.isFile(), expected);
320 }
321
322
isDir_data()323 void tst_QFileInfo::isDir_data()
324 {
325 // create a broken symlink
326 QFile::remove("brokenlink.lnk");
327 QFile::remove("dummyfile");
328 QFile file3("dummyfile");
329 file3.open(QIODevice::WriteOnly);
330 if (file3.link("brokenlink.lnk")) {
331 file3.remove();
332 QFileInfo info3("brokenlink.lnk");
333 QVERIFY( info3.isSymLink() );
334 }
335
336 QTest::addColumn<QString>("path");
337 QTest::addColumn<bool>("expected");
338
339 QTest::newRow("data0") << QDir::currentPath() << true;
340 QTest::newRow("data1") << SRCDIR "tst_qfileinfo.cpp" << false;
341 QTest::newRow("data2") << ":/tst_qfileinfo/resources/" << true;
342 QTest::newRow("data3") << ":/tst_qfileinfo/resources/file1" << false;
343 QTest::newRow("data4") << ":/tst_qfileinfo/resources/afilethatshouldnotexist" << false;
344
345 QTest::newRow("simple dir") << SRCDIR "resources" << true;
346 QTest::newRow("simple dir with slash") << SRCDIR "resources/" << true;
347
348 QTest::newRow("broken link") << "brokenlink.lnk" << false;
349
350 #if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
351 QTest::newRow("drive 1") << "c:" << true;
352 QTest::newRow("drive 2") << "c:/" << true;
353 //QTest::newRow("drive 2") << "t:s" << false;
354 #endif
355 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
356 QTest::newRow("unc 1") << "//" + QtNetworkSettings::winServerName() << true;
357 QTest::newRow("unc 2") << "//" + QtNetworkSettings::winServerName() + "/" << true;
358 QTest::newRow("unc 3") << "//" + QtNetworkSettings::winServerName() + "/testshare" << true;
359 QTest::newRow("unc 4") << "//" + QtNetworkSettings::winServerName() + "/testshare/" << true;
360 QTest::newRow("unc 5") << "//" + QtNetworkSettings::winServerName() + "/testshare/tmp" << true;
361 QTest::newRow("unc 6") << "//" + QtNetworkSettings::winServerName() + "/testshare/tmp/" << true;
362 QTest::newRow("unc 7") << "//" + QtNetworkSettings::winServerName() + "/testshare/adirthatshouldnotexist" << false;
363 #endif
364 }
365
isDir()366 void tst_QFileInfo::isDir()
367 {
368 QFETCH(QString, path);
369 QFETCH(bool, expected);
370
371 QFileInfo fi(path);
372 QCOMPARE(fi.isDir(), expected);
373 }
374
isRoot_data()375 void tst_QFileInfo::isRoot_data()
376 {
377 QTest::addColumn<QString>("path");
378 QTest::addColumn<bool>("expected");
379 QTest::newRow("data0") << QDir::currentPath() << false;
380 QTest::newRow("data1") << "/" << true;
381 QTest::newRow("data2") << "*" << false;
382 QTest::newRow("data3") << "/*" << false;
383 QTest::newRow("data4") << ":/tst_qfileinfo/resources/" << false;
384 QTest::newRow("data5") << ":/" << true;
385
386 QTest::newRow("simple dir") << SRCDIR "resources" << false;
387 QTest::newRow("simple dir with slash") << SRCDIR "resources/" << false;
388 #if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
389 QTest::newRow("drive 1") << "c:" << false;
390 QTest::newRow("drive 2") << "c:/" << true;
391 QTest::newRow("drive 3") << "p:/" << false;
392 #endif
393
394 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
395 QTest::newRow("unc 1") << "//" + QtNetworkSettings::winServerName() << true;
396 QTest::newRow("unc 2") << "//" + QtNetworkSettings::winServerName() + "/" << true;
397 QTest::newRow("unc 3") << "//" + QtNetworkSettings::winServerName() + "/testshare" << false;
398 QTest::newRow("unc 4") << "//" + QtNetworkSettings::winServerName() + "/testshare/" << false;
399 QTest::newRow("unc 7") << "//ahostthatshouldnotexist" << false;
400 #endif
401 }
402
isRoot()403 void tst_QFileInfo::isRoot()
404 {
405 QFETCH(QString, path);
406 QFETCH(bool, expected);
407
408 QFileInfo fi(path);
409 QCOMPARE(fi.isRoot(), expected);
410 }
411
exists_data()412 void tst_QFileInfo::exists_data()
413 {
414 QTest::addColumn<QString>("path");
415 QTest::addColumn<bool>("expected");
416
417 QTest::newRow("data0") << QDir::currentPath() << true;
418 QTest::newRow("data1") << SRCDIR "tst_qfileinfo.cpp" << true;
419 QTest::newRow("data2") << "/I/do_not_expect_this_path_to_exist/" << false;
420 QTest::newRow("data3") << ":/tst_qfileinfo/resources/" << true;
421 QTest::newRow("data4") << ":/tst_qfileinfo/resources/file1" << true;
422 QTest::newRow("data5") << ":/I/do_not_expect_this_path_to_exist/" << false;
423 QTest::newRow("data6") << SRCDIR "resources/*" << false;
424 QTest::newRow("data7") << SRCDIR "resources/*.foo" << false;
425 QTest::newRow("data8") << SRCDIR "resources/*.ext1" << false;
426 QTest::newRow("data9") << SRCDIR "resources/file?.ext1" << false;
427 QTest::newRow("data10") << "." << true;
428 QTest::newRow("data11") << ". " << false;
429 QTest::newRow("empty") << "" << false;
430
431 QTest::newRow("simple dir") << SRCDIR "resources" << true;
432 QTest::newRow("simple dir with slash") << SRCDIR "resources/" << true;
433
434 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
435 QTest::newRow("unc 1") << "//" + QtNetworkSettings::winServerName() << true;
436 QTest::newRow("unc 2") << "//" + QtNetworkSettings::winServerName() + "/" << true;
437 QTest::newRow("unc 3") << "//" + QtNetworkSettings::winServerName() + "/testshare" << true;
438 QTest::newRow("unc 4") << "//" + QtNetworkSettings::winServerName() + "/testshare/" << true;
439 QTest::newRow("unc 5") << "//" + QtNetworkSettings::winServerName() + "/testshare/tmp" << true;
440 QTest::newRow("unc 6") << "//" + QtNetworkSettings::winServerName() + "/testshare/tmp/" << true;
441 QTest::newRow("unc 7") << "//" + QtNetworkSettings::winServerName() + "/testshare/adirthatshouldnotexist" << false;
442 QTest::newRow("unc 8") << "//" + QtNetworkSettings::winServerName() + "/asharethatshouldnotexist" << false;
443 QTest::newRow("unc 9") << "//ahostthatshouldnotexist" << false;
444 #endif
445 }
446
exists()447 void tst_QFileInfo::exists()
448 {
449 QFETCH(QString, path);
450 QFETCH(bool, expected);
451
452 QFileInfo fi(path);
453 QCOMPARE(fi.exists(), expected);
454 }
455
absolutePath_data()456 void tst_QFileInfo::absolutePath_data()
457 {
458 QTest::addColumn<QString>("file");
459 QTest::addColumn<QString>("path");
460 QTest::addColumn<QString>("filename");
461
462 QString drivePrefix;
463 #if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
464 drivePrefix = QDir::currentPath().left(2);
465 QString nonCurrentDrivePrefix =
466 drivePrefix.left(1).compare("X", Qt::CaseInsensitive) == 0 ? QString("Y:") : QString("X:");
467
468 // Make sure drive-relative paths return correct absolute paths (task 255326)
469 QTest::newRow("<current drive>:my.dll") << drivePrefix + "my.dll" << QDir::currentPath() << "my.dll";
470 QTest::newRow("<not current drive>:my.dll") << nonCurrentDrivePrefix + "my.dll"
471 << nonCurrentDrivePrefix + "/"
472 << "my.dll";
473 #endif
474 QTest::newRow("0") << "/machine/share/dir1/" << drivePrefix + "/machine/share/dir1" << "";
475 QTest::newRow("1") << "/machine/share/dir1" << drivePrefix + "/machine/share" << "dir1";
476 QTest::newRow("2") << "/usr/local/bin" << drivePrefix + "/usr/local" << "bin";
477 QTest::newRow("3") << "/usr/local/bin/" << drivePrefix + "/usr/local/bin" << "";
478 QTest::newRow("/test") << "/test" << drivePrefix + "/" << "test";
479
480 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
481 // see task 102898
482 QTest::newRow("c:\\autoexec.bat") << "c:\\autoexec.bat" << "C:/"
483 << "autoexec.bat";
484 QTest::newRow("c:autoexec.bat") << QDir::currentPath().left(2) + "autoexec.bat" << QDir::currentPath()
485 << "autoexec.bat";
486 #endif
487 QTest::newRow("QTBUG-19995.1") << drivePrefix + "/System/Library/StartupItems/../Frameworks"
488 << drivePrefix + "/System/Library"
489 << "Frameworks";
490 QTest::newRow("QTBUG-19995.2") << drivePrefix + "/System/Library/StartupItems/../Frameworks/"
491 << drivePrefix + "/System/Library/Frameworks" << "";
492 }
493
absolutePath()494 void tst_QFileInfo::absolutePath()
495 {
496 QFETCH(QString, file);
497 QFETCH(QString, path);
498 QFETCH(QString, filename);
499
500 QFileInfo fi(file);
501
502 QCOMPARE(fi.absolutePath(), path);
503 QCOMPARE(fi.fileName(), filename);
504 }
505
absFilePath_data()506 void tst_QFileInfo::absFilePath_data()
507 {
508 QTest::addColumn<QString>("file");
509 QTest::addColumn<QString>("expected");
510
511 QTest::newRow("relativeFile") << "tmp.txt" << QDir::currentPath() + "/tmp.txt";
512 QTest::newRow("relativeFileInSubDir") << "temp/tmp.txt" << QDir::currentPath() + "/" + "temp/tmp.txt";
513 QString drivePrefix;
514 #if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
515 QString curr = QDir::currentPath();
516
517 curr.remove(0, 2); // Make it a absolute path with no drive specifier: \depot\qt-4.2\tests\auto\qfileinfo
518 QTest::newRow(".") << curr << QDir::currentPath();
519 QTest::newRow("absFilePath") << "c:\\home\\andy\\tmp.txt" << "C:/home/andy/tmp.txt";
520
521 // Make sure drive-relative paths return correct absolute paths (task 255326)
522 drivePrefix = QDir::currentPath().left(2);
523 QString nonCurrentDrivePrefix =
524 drivePrefix.left(1).compare("X", Qt::CaseInsensitive) == 0 ? QString("Y:") : QString("X:");
525
526 QTest::newRow("absFilePathWithoutSlash") << drivePrefix + "tmp.txt" << QDir::currentPath() + "/tmp.txt";
527 QTest::newRow("<current drive>:my.dll") << drivePrefix + "temp/my.dll" << QDir::currentPath() + "/temp/my.dll";
528 QTest::newRow("<not current drive>:my.dll") << nonCurrentDrivePrefix + "temp/my.dll"
529 << nonCurrentDrivePrefix + "/temp/my.dll";
530 #else
531 QTest::newRow("absFilePath") << "/home/andy/tmp.txt" << "/home/andy/tmp.txt";
532 #endif
533 QTest::newRow("QTBUG-19995") << drivePrefix + "/System/Library/StartupItems/../Frameworks"
534 << drivePrefix + "/System/Library/Frameworks";
535 }
536
absFilePath()537 void tst_QFileInfo::absFilePath()
538 {
539 QFETCH(QString, file);
540 QFETCH(QString, expected);
541
542 QFileInfo fi(file);
543 #if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
544 QVERIFY(QString::compare(fi.absoluteFilePath(), expected, Qt::CaseInsensitive) == 0);
545 #else
546 QCOMPARE(fi.absoluteFilePath(), expected);
547 #endif
548 }
549
canonicalPath()550 void tst_QFileInfo::canonicalPath()
551 {
552 QTemporaryFile tempFile;
553 tempFile.setAutoRemove(true);
554 tempFile.open();
555 QFileInfo fi(tempFile.fileName());
556 QCOMPARE(fi.canonicalPath(), QFileInfo(QDir::tempPath()).canonicalFilePath());
557 }
558
canonicalFilePath()559 void tst_QFileInfo::canonicalFilePath()
560 {
561 const QString fileName("tmp.canon");
562 QFile tempFile(fileName);
563 QVERIFY(tempFile.open(QFile::WriteOnly));
564 QFileInfo fi(tempFile.fileName());
565 QCOMPARE(fi.canonicalFilePath(), QDir::currentPath() + "/" + fileName);
566 tempFile.remove();
567
568 // This used to crash on Mac, verify that it doesn't anymore.
569 QFileInfo info("/tmp/../../../../../../../../../../../../../../../../../");
570 info.canonicalFilePath();
571
572 #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
573 // This used to crash on Mac
574 QFileInfo dontCrash(QLatin1String("/"));
575 QCOMPARE(dontCrash.canonicalFilePath(), QLatin1String("/"));
576 #endif
577
578 #ifndef Q_OS_WIN
579 // test symlinks
580 QFile::remove("link.lnk");
581 {
582 QFile file(SRCDIR "tst_qfileinfo.cpp");
583 if (file.link("link.lnk")) {
584 QFileInfo info1(file);
585 QFileInfo info2("link.lnk");
586 QCOMPARE(info1.canonicalFilePath(), info2.canonicalFilePath());
587 }
588 }
589 # if !defined(Q_OS_SYMBIAN)
590 // Symbian doesn't support links to directories
591 {
592 const QString link(QDir::tempPath() + QDir::separator() + "tst_qfileinfo");
593 QFile::remove(link);
594 QFile file(QDir::currentPath());
595 if (file.link(link)) {
596 QFile tempfile("tempfile.txt");
597 tempfile.open(QIODevice::ReadWrite);
598 tempfile.write("This file is generated by the QFileInfo autotest.");
599 QVERIFY(tempfile.flush());
600 tempfile.close();
601
602 QFileInfo info1("tempfile.txt");
603 QFileInfo info2(link + QDir::separator() + "tempfile.txt");
604
605 QVERIFY(info1.exists());
606 QVERIFY(info2.exists());
607 QCOMPARE(info1.canonicalFilePath(), info2.canonicalFilePath());
608
609 QFileInfo info3(link + QDir::separator() + "link.lnk");
610 QFileInfo info4(SRCDIR "tst_qfileinfo.cpp");
611 QVERIFY(!info3.canonicalFilePath().isEmpty());
612 QCOMPARE(info4.canonicalFilePath(), info3.canonicalFilePath());
613
614 tempfile.remove();
615 }
616 }
617 {
618 QString link(QDir::tempPath() + QDir::separator() + "tst_qfileinfo"
619 + QDir::separator() + "link_to_tst_qfileinfo");
620 QFile::remove(link);
621
622 QFile file(QDir::tempPath() + QDir::separator() + "tst_qfileinfo"
623 + QDir::separator() + "tst_qfileinfo.cpp");
624 if (file.link(link))
625 {
626 QFileInfo info1("tst_qfileinfo.cpp");
627 QFileInfo info2(link);
628 QCOMPARE(info1.canonicalFilePath(), info2.canonicalFilePath());
629 }
630 }
631 # endif
632 #endif
633
634 #ifdef Q_OS_WIN
635 typedef BOOL (WINAPI *PtrCreateSymbolicLink)(LPTSTR, LPTSTR, DWORD);
636 PtrCreateSymbolicLink ptrCreateSymbolicLink =
637 (PtrCreateSymbolicLink)QLibrary::resolve(QLatin1String("kernel32"), "CreateSymbolicLinkW");
638
639 if (!ptrCreateSymbolicLink) {
640 QSKIP("Symbolic links aren't supported by FS", SkipAll);
641 } else {
642 // CreateSymbolicLink can return TRUE & still fail to create the link,
643 // the error code in that case is ERROR_PRIVILEGE_NOT_HELD (1314)
644 SetLastError(0);
645 BOOL ret = ptrCreateSymbolicLink((wchar_t*)QString("res").utf16(), (wchar_t*)QString("resources").utf16(), 1);
646 DWORD dwErr = GetLastError();
647 if (!ret)
648 QSKIP("Symbolic links aren't supported by FS", SkipAll);
649 QString currentPath = QDir::currentPath();
650 bool is_res_Current = QDir::setCurrent("res");
651 if (!is_res_Current && dwErr == 1314)
652 QSKIP("Not enough privilages to create Symbolic links", SkipAll);
653 QCOMPARE(is_res_Current, true);
654
655 QCOMPARE(QFileInfo("file1").canonicalFilePath(), currentPath + "/resources/file1");
656
657 QCOMPARE(QDir::setCurrent(currentPath), true);
658 QDir::current().rmdir("res");
659 }
660 #endif
661 }
662
fileName_data()663 void tst_QFileInfo::fileName_data()
664 {
665 QTest::addColumn<QString>("file");
666 QTest::addColumn<QString>("expected");
667
668 QTest::newRow("relativeFile") << "tmp.txt" << "tmp.txt";
669 QTest::newRow("relativeFileInSubDir") << "temp/tmp.txt" << "tmp.txt";
670 #if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
671 QTest::newRow("absFilePath") << "c:\\home\\andy\\tmp.txt" << "tmp.txt";
672 QTest::newRow("driveWithNoSlash") << "c:tmp.txt" << "tmp.txt";
673 #else
674 QTest::newRow("absFilePath") << "/home/andy/tmp.txt" << "tmp.txt";
675 #endif
676 QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << "file1.ext1";
677 QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1.ext2" << "file1.ext1.ext2";
678
679 QTest::newRow("ending slash [small]") << QString::fromLatin1("/a/") << QString::fromLatin1("");
680 QTest::newRow("no ending slash [small]") << QString::fromLatin1("/a") << QString::fromLatin1("a");
681
682 QTest::newRow("ending slash") << QString::fromLatin1("/somedir/") << QString::fromLatin1("");
683 QTest::newRow("no ending slash") << QString::fromLatin1("/somedir") << QString::fromLatin1("somedir");
684 }
685
fileName()686 void tst_QFileInfo::fileName()
687 {
688 QFETCH(QString, file);
689 QFETCH(QString, expected);
690
691 QFileInfo fi(file);
692 QCOMPARE(fi.fileName(), expected);
693 }
694
bundleName_data()695 void tst_QFileInfo::bundleName_data()
696 {
697 QTest::addColumn<QString>("file");
698 QTest::addColumn<QString>("expected");
699
700 QTest::newRow("root") << "/" << "";
701 QTest::newRow("etc") << "/etc" << "";
702 #ifdef Q_OS_MAC
703 QTest::newRow("safari") << "/Applications/Safari.app" << "Safari";
704 #endif
705 }
706
bundleName()707 void tst_QFileInfo::bundleName()
708 {
709 QFETCH(QString, file);
710 QFETCH(QString, expected);
711
712 QFileInfo fi(file);
713 QCOMPARE(fi.bundleName(), expected);
714 }
715
dir_data()716 void tst_QFileInfo::dir_data()
717 {
718 QTest::addColumn<QString>("file");
719 QTest::addColumn<bool>("absPath");
720 QTest::addColumn<QString>("expected");
721
722 QTest::newRow("relativeFile") << "tmp.txt" << false << ".";
723 QTest::newRow("relativeFileAbsPath") << "tmp.txt" << true << QDir::currentPath();
724 QTest::newRow("relativeFileInSubDir") << "temp/tmp.txt" << false << "temp";
725 QTest::newRow("relativeFileInSubDirAbsPath") << "temp/tmp.txt" << true << QDir::currentPath() + "/temp";
726 QTest::newRow("absFilePath") << QDir::currentPath() + "/tmp.txt" << false << QDir::currentPath();
727 QTest::newRow("absFilePathAbsPath") << QDir::currentPath() + "/tmp.txt" << true << QDir::currentPath();
728 QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << true << ":/tst_qfileinfo/resources";
729 #ifdef Q_OS_WIN
730 QTest::newRow("driveWithSlash") << "C:/file1.ext1.ext2" << true << "C:/";
731 QTest::newRow("driveWithoutSlash") << QDir::currentPath().left(2) + "file1.ext1.ext2" << false << QDir::currentPath().left(2);
732 #endif
733 }
734
dir()735 void tst_QFileInfo::dir()
736 {
737 QFETCH(QString, file);
738 QFETCH(bool, absPath);
739 QFETCH(QString, expected);
740
741 QFileInfo fi(file);
742 if (absPath) {
743 QCOMPARE(fi.absolutePath(), expected);
744 QCOMPARE(fi.absoluteDir().path(), expected);
745 #ifdef QT3_SUPPORT
746 QCOMPARE(fi.dir(true).path(), expected);
747 #endif
748 } else {
749 QCOMPARE(fi.path(), expected);
750 QCOMPARE(fi.dir().path(), expected);
751 #ifdef QT3_SUPPORT
752 QCOMPARE(fi.dir(false).path(), expected);
753 #endif
754 }
755 }
756
757
suffix_data()758 void tst_QFileInfo::suffix_data()
759 {
760 QTest::addColumn<QString>("file");
761 QTest::addColumn<QString>("expected");
762
763 QTest::newRow("noextension0") << "file" << "";
764 QTest::newRow("noextension1") << "/path/to/file" << "";
765 QTest::newRow("data0") << "file.tar" << "tar";
766 QTest::newRow("data1") << "file.tar.gz" << "gz";
767 QTest::newRow("data2") << "/path/file/file.tar.gz" << "gz";
768 QTest::newRow("data3") << "/path/file.tar" << "tar";
769 QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << "ext1";
770 QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1.ext2" << "ext2";
771 QTest::newRow("hidden1") << ".ext1" << "ext1";
772 QTest::newRow("hidden1") << ".ext" << "ext";
773 QTest::newRow("hidden1") << ".ex" << "ex";
774 QTest::newRow("hidden1") << ".e" << "e";
775 QTest::newRow("hidden2") << ".ext1.ext2" << "ext2";
776 QTest::newRow("hidden2") << ".ext.ext2" << "ext2";
777 QTest::newRow("hidden2") << ".ex.ext2" << "ext2";
778 QTest::newRow("hidden2") << ".e.ext2" << "ext2";
779 QTest::newRow("hidden2") << "..ext2" << "ext2";
780 #ifdef Q_OS_WIN
781 QTest::newRow("driveWithSlash") << "c:/file1.ext1.ext2" << "ext2";
782 QTest::newRow("driveWithoutSlash") << "c:file1.ext1.ext2" << "ext2";
783 #endif
784 }
785
suffix()786 void tst_QFileInfo::suffix()
787 {
788 QFETCH(QString, file);
789 QFETCH(QString, expected);
790
791 QFileInfo fi(file);
792 QCOMPARE(fi.suffix(), expected);
793 }
794
795
completeSuffix_data()796 void tst_QFileInfo::completeSuffix_data()
797 {
798 QTest::addColumn<QString>("file");
799 QTest::addColumn<QString>("expected");
800
801 QTest::newRow("noextension0") << "file" << "";
802 QTest::newRow("noextension1") << "/path/to/file" << "";
803 QTest::newRow("data0") << "file.tar" << "tar";
804 QTest::newRow("data1") << "file.tar.gz" << "tar.gz";
805 QTest::newRow("data2") << "/path/file/file.tar.gz" << "tar.gz";
806 QTest::newRow("data3") << "/path/file.tar" << "tar";
807 QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << "ext1";
808 QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1.ext2" << "ext1.ext2";
809 #ifdef Q_OS_WIN
810 QTest::newRow("driveWithSlash") << "c:/file1.ext1.ext2" << "ext1.ext2";
811 QTest::newRow("driveWithoutSlash") << "c:file1.ext1.ext2" << "ext1.ext2";
812 #endif
813 }
814
completeSuffix()815 void tst_QFileInfo::completeSuffix()
816 {
817 QFETCH(QString, file);
818 QFETCH(QString, expected);
819
820 QFileInfo fi(file);
821 QCOMPARE(fi.completeSuffix(), expected);
822 }
823
baseName_data()824 void tst_QFileInfo::baseName_data()
825 {
826 QTest::addColumn<QString>("file");
827 QTest::addColumn<QString>("expected");
828
829 QTest::newRow("data0") << "file.tar" << "file";
830 QTest::newRow("data1") << "file.tar.gz" << "file";
831 QTest::newRow("data2") << "/path/file/file.tar.gz" << "file";
832 QTest::newRow("data3") << "/path/file.tar" << "file";
833 QTest::newRow("data4") << "/path/file" << "file";
834 QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << "file1";
835 QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1.ext2" << "file1";
836 #ifdef Q_OS_WIN
837 QTest::newRow("driveWithSlash") << "c:/file1.ext1.ext2" << "file1";
838 QTest::newRow("driveWithoutSlash") << "c:file1.ext1.ext2" << "file1";
839 #endif
840 }
841
baseName()842 void tst_QFileInfo::baseName()
843 {
844 QFETCH(QString, file);
845 QFETCH(QString, expected);
846
847 QFileInfo fi(file);
848 QCOMPARE(fi.baseName(), expected);
849 }
850
completeBaseName_data()851 void tst_QFileInfo::completeBaseName_data()
852 {
853 QTest::addColumn<QString>("file");
854 QTest::addColumn<QString>("expected");
855
856 QTest::newRow("data0") << "file.tar" << "file";
857 QTest::newRow("data1") << "file.tar.gz" << "file.tar";
858 QTest::newRow("data2") << "/path/file/file.tar.gz" << "file.tar";
859 QTest::newRow("data3") << "/path/file.tar" << "file";
860 QTest::newRow("data4") << "/path/file" << "file";
861 QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << "file1";
862 QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1.ext2" << "file1.ext1";
863 #ifdef Q_OS_WIN
864 QTest::newRow("driveWithSlash") << "c:/file1.ext1.ext2" << "file1.ext1";
865 QTest::newRow("driveWithoutSlash") << "c:file1.ext1.ext2" << "file1.ext1";
866 #endif
867 }
868
completeBaseName()869 void tst_QFileInfo::completeBaseName()
870 {
871 QFETCH(QString, file);
872 QFETCH(QString, expected);
873
874 QFileInfo fi(file);
875 QCOMPARE(fi.completeBaseName(), expected);
876 }
877
permission_data()878 void tst_QFileInfo::permission_data()
879 {
880 QTest::addColumn<QString>("file");
881 QTest::addColumn<int>("perms");
882 QTest::addColumn<bool>("expected");
883
884 QTest::newRow("data0") << QCoreApplication::instance()->applicationFilePath() << int(QFile::ExeUser) << true;
885 QTest::newRow("data1") << SRCDIR "tst_qfileinfo.cpp" << int(QFile::ReadUser) << true;
886 // QTest::newRow("data2") << "tst_qfileinfo.cpp" << int(QFile::WriteUser) << false;
887 QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << int(QFile::ReadUser) << true;
888 QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1" << int(QFile::WriteUser) << false;
889 QTest::newRow("resource3") << ":/tst_qfileinfo/resources/file1.ext1" << int(QFile::ExeUser) << false;
890 }
891
permission()892 void tst_QFileInfo::permission()
893 {
894 QFETCH(QString, file);
895 QFETCH(int, perms);
896 QFETCH(bool, expected);
897 #ifdef Q_OS_SYMBIAN
898 QSKIP("No user based rights in Symbian OS - SOS needs platform security tests instead", SkipAll);
899 #endif
900 QFileInfo fi(file);
901 QCOMPARE(fi.permission(QFile::Permissions(perms)), expected);
902 }
903
size_data()904 void tst_QFileInfo::size_data()
905 {
906 QTest::addColumn<QString>("file");
907 QTest::addColumn<int>("size");
908
909 QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << 0;
910 QFile::remove("file1");
911 QFile file("file1");
912 QVERIFY(file.open(QFile::WriteOnly));
913 QCOMPARE(file.write("JAJAJAA"), qint64(7));
914 QTest::newRow("created-file") << "file1" << 7;
915
916 QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1.ext2" << 0;
917 }
918
size()919 void tst_QFileInfo::size()
920 {
921 QFETCH(QString, file);
922
923 QFileInfo fi(file);
924 (void)fi.permissions(); // see task 104198
925 QTEST(int(fi.size()), "size");
926 }
927
systemFiles()928 void tst_QFileInfo::systemFiles()
929 {
930 #if !defined(Q_OS_WIN) || defined(Q_OS_WINCE)
931 QSKIP("This is a Windows only test", SkipAll);
932 #endif
933 QFileInfo fi("c:\\pagefile.sys");
934 QVERIFY(fi.exists()); // task 167099
935 QVERIFY(fi.size() > 0); // task 189202
936 QVERIFY(fi.lastModified().isValid());
937 }
938
compare_data()939 void tst_QFileInfo::compare_data()
940 {
941 QTest::addColumn<QString>("file1");
942 QTest::addColumn<QString>("file2");
943 QTest::addColumn<bool>("same");
944
945 #if defined(Q_OS_MAC)
946 // Since 10.6 we use realpath() in qfsfileengine, and it properly handles
947 // file system case sensitivity. However here in the autotest we don't
948 // check if the file system is case sensitive, so to make it pass in the
949 // default OS X installation we assume we are running on a case insensitive
950 // file system if on 10.6 and on a case sensitive file system if on 10.5
951 bool caseSensitiveOnMac = true;
952 if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6)
953 caseSensitiveOnMac = false;
954 #endif
955
956 QTest::newRow("data0")
957 << QString::fromLatin1(SRCDIR "tst_qfileinfo.cpp")
958 << QString::fromLatin1(SRCDIR "tst_qfileinfo.cpp")
959 << true;
960 QTest::newRow("data1")
961 << QString::fromLatin1(SRCDIR "tst_qfileinfo.cpp")
962 << QString::fromLatin1("/tst_qfileinfo.cpp")
963 << false;
964 QTest::newRow("data2")
965 << QString::fromLatin1("tst_qfileinfo.cpp")
966 << QDir::currentPath() + QString::fromLatin1("/tst_qfileinfo.cpp")
967 << true;
968 QTest::newRow("casesense1")
969 << QString::fromLatin1(SRCDIR "tst_qfileInfo.cpp")
970 << QString::fromLatin1(SRCDIR "tst_qfileinfo.cpp")
971 #if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
972 << true;
973 #elif defined(Q_OS_MAC)
974 << !caseSensitiveOnMac;
975 #else
976 << false;
977 #endif
978 }
979
compare()980 void tst_QFileInfo::compare()
981 {
982 QFETCH(QString, file1);
983 QFETCH(QString, file2);
984 QFETCH(bool, same);
985 QFileInfo fi1(file1), fi2(file2);
986 QCOMPARE(fi1 == fi2, same);
987 }
988
consistent_data()989 void tst_QFileInfo::consistent_data()
990 {
991 QTest::addColumn<QString>("file");
992 QTest::addColumn<QString>("expected");
993
994 #if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
995 QTest::newRow("slashes") << QString::fromLatin1("\\a\\a\\a\\a") << QString::fromLatin1("/a/a/a/a");
996 #endif
997 QTest::newRow("ending slash") << QString::fromLatin1("/a/somedir/") << QString::fromLatin1("/a/somedir/");
998 QTest::newRow("no ending slash") << QString::fromLatin1("/a/somedir") << QString::fromLatin1("/a/somedir");
999 }
1000
consistent()1001 void tst_QFileInfo::consistent()
1002 {
1003 QFETCH(QString, file);
1004 QFETCH(QString, expected);
1005
1006 QFileInfo fi(file);
1007 QCOMPARE(fi.filePath(), expected);
1008 QCOMPARE(fi.dir().path() + "/" + fi.fileName(), expected);
1009 }
1010
1011
fileTimes_data()1012 void tst_QFileInfo::fileTimes_data()
1013 {
1014 QTest::addColumn<QString>("fileName");
1015 QTest::newRow("simple") << QString::fromLatin1("simplefile.txt");
1016 QTest::newRow( "longfile" ) << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
1017 "longFileNamelongFileNamelongFileNamelongFileName"
1018 "longFileNamelongFileNamelongFileNamelongFileName"
1019 "longFileNamelongFileNamelongFileNamelongFileName"
1020 "longFileNamelongFileNamelongFileNamelongFileName.txt");
1021 QTest::newRow( "longfile absolutepath" ) << QFileInfo(QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
1022 "longFileNamelongFileNamelongFileNamelongFileName"
1023 "longFileNamelongFileNamelongFileNamelongFileName"
1024 "longFileNamelongFileNamelongFileNamelongFileName"
1025 "longFileNamelongFileNamelongFileNamelongFileName.txt")).absoluteFilePath();
1026 }
1027
fileTimes()1028 void tst_QFileInfo::fileTimes()
1029 {
1030 #if defined(Q_OS_WINCE)
1031 int sleepTime = 3000;
1032 #else
1033 int sleepTime = 2000;
1034 #endif
1035 QFETCH(QString, fileName);
1036 if (QFile::exists(fileName)) {
1037 QVERIFY(QFile::remove(fileName));
1038 }
1039 QTest::qSleep(sleepTime);
1040 {
1041 QFile file(fileName);
1042 #if defined(Q_OS_WINCE)
1043 QEXPECT_FAIL("longfile", "No long filenames on WinCE", Abort);
1044 QEXPECT_FAIL("longfile absolutepath", "No long filenames on WinCE", Abort);
1045 #elif defined(Q_OS_SYMBIAN)
1046 QEXPECT_FAIL("longfile", "Maximum total filepath cannot exceed 256 characters in Symbian", Abort);
1047 QEXPECT_FAIL("longfile absolutepath", "Maximum total filepath cannot exceed 256 characters in Symbian", Abort);
1048 #endif
1049 QVERIFY(file.open(QFile::WriteOnly | QFile::Text));
1050 #ifdef Q_OS_UNIX
1051 if (qIsLikelyToBeNfs(file.handle()))
1052 QSKIP("This Test doesn't work on NFS", SkipAll);
1053 #endif
1054 QTextStream ts(&file);
1055 ts << fileName << endl;
1056 }
1057 QTest::qSleep(sleepTime);
1058 QDateTime beforeWrite = QDateTime::currentDateTime();
1059 QTest::qSleep(sleepTime);
1060 {
1061 QFileInfo fileInfo(fileName);
1062 QVERIFY(fileInfo.created() < beforeWrite);
1063 QFile file(fileName);
1064 QVERIFY(file.open(QFile::ReadWrite | QFile::Text));
1065 QTextStream ts(&file);
1066 ts << fileName << endl;
1067 }
1068 QTest::qSleep(sleepTime);
1069 QDateTime beforeRead = QDateTime::currentDateTime();
1070 QTest::qSleep(sleepTime);
1071 {
1072 QFileInfo fileInfo(fileName);
1073 // On unix created() returns the same as lastModified().
1074 #if !defined(Q_OS_UNIX) && !defined(Q_OS_WINCE)
1075 QVERIFY(fileInfo.created() < beforeWrite);
1076 #endif
1077 QVERIFY(fileInfo.lastModified() > beforeWrite);
1078 QFile file(fileName);
1079 QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
1080 QTextStream ts(&file);
1081 QString line = ts.readLine();
1082 QCOMPARE(line, fileName);
1083 }
1084
1085 QFileInfo fileInfo(fileName);
1086 #if !defined(Q_OS_UNIX) && !defined(Q_OS_WINCE)
1087 QVERIFY(fileInfo.created() < beforeWrite);
1088 #endif
1089 //In Vista the last-access timestamp is not updated when the file is accessed/touched (by default).
1090 //To enable this the HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisableLastAccessUpdate
1091 //is set to 0, in the test machine.
1092 #ifdef Q_OS_WIN
1093 HKEY key;
1094 if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\FileSystem",
1095 0, KEY_READ, &key)) {
1096 DWORD disabledAccessTimes = 0;
1097 DWORD size = sizeof(DWORD);
1098 LONG error = RegQueryValueEx(key, L"NtfsDisableLastAccessUpdate"
1099 , NULL, NULL, (LPBYTE)&disabledAccessTimes, &size);
1100 if (ERROR_SUCCESS == error && disabledAccessTimes)
1101 QEXPECT_FAIL("", "File access times are disabled in windows registry (this is the default setting)", Continue);
1102 RegCloseKey(key);
1103 }
1104 #endif
1105 #if defined(Q_OS_WINCE)
1106 QEXPECT_FAIL("simple", "WinCE only stores date of access data, not the time", Continue);
1107 #elif defined(Q_OS_SYMBIAN)
1108 QEXPECT_FAIL("simple", "Symbian implementation of stat doesn't return read time right", Abort);
1109 #elif defined(Q_OS_BLACKBERRY)
1110 QEXPECT_FAIL("simple", "Blackberry OS uses the noatime filesystem option", Continue);
1111 QEXPECT_FAIL("longfile", "Blackberry OS uses the noatime filesystem option", Continue);
1112 QEXPECT_FAIL("longfile absolutepath", "Blackberry OS uses the noatime filesystem option", Continue);
1113 #endif
1114 QVERIFY(fileInfo.lastRead() > beforeRead);
1115 QVERIFY(fileInfo.lastModified() > beforeWrite);
1116 QVERIFY(fileInfo.lastModified() < beforeRead);
1117 }
1118
fileTimes_oldFile()1119 void tst_QFileInfo::fileTimes_oldFile()
1120 {
1121 // This is not supported on WinCE
1122 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
1123 // All files are opened in share mode (both read and write).
1124 DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
1125
1126 // All files on Windows can be read; there's no such thing as an
1127 // unreadable file. Add GENERIC_WRITE if WriteOnly is passed.
1128 int accessRights = GENERIC_READ | GENERIC_WRITE;
1129
1130 SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
1131
1132 // Regular file mode. In Unbuffered mode, pass the no-buffering flag.
1133 DWORD flagsAndAtts = FILE_ATTRIBUTE_NORMAL;
1134
1135 // WriteOnly can create files, ReadOnly cannot.
1136 DWORD creationDisp = OPEN_ALWAYS;
1137
1138 // Create the file handle.
1139 HANDLE fileHandle = CreateFile(L"oldfile.txt",
1140 accessRights,
1141 shareMode,
1142 &securityAtts,
1143 creationDisp,
1144 flagsAndAtts,
1145 NULL);
1146
1147 // Set file times back to 1601.
1148 SYSTEMTIME stime;
1149 stime.wYear = 1601;
1150 stime.wMonth = 1;
1151 stime.wDayOfWeek = 1;
1152 stime.wDay = 1;
1153 stime.wHour = 1;
1154 stime.wMinute = 0;
1155 stime.wSecond = 0;
1156 stime.wMilliseconds = 0;
1157
1158 FILETIME ctime;
1159 QVERIFY(SystemTimeToFileTime(&stime, &ctime));
1160 FILETIME atime = ctime;
1161 FILETIME mtime = atime;
1162 QVERIFY(fileHandle);
1163 QVERIFY(SetFileTime(fileHandle, &ctime, &atime, &mtime) != 0);
1164
1165 CloseHandle(fileHandle);
1166
1167 QFileInfo info("oldfile.txt");
1168 QCOMPARE(info.lastModified(), QDateTime(QDate(1601, 1, 1), QTime(1, 0), Qt::UTC).toLocalTime());
1169 #endif
1170 }
1171
isSymLink_data()1172 void tst_QFileInfo::isSymLink_data()
1173 {
1174 #ifndef NO_SYMLINKS
1175 QFile::remove("link.lnk");
1176 QFile::remove("brokenlink.lnk");
1177 QFile::remove("dummyfile");
1178
1179 QFile file1(SRCDIR "tst_qfileinfo.cpp");
1180 QVERIFY(file1.link("link.lnk"));
1181
1182 QFile file2("dummyfile");
1183 file2.open(QIODevice::WriteOnly);
1184 QVERIFY(file2.link("brokenlink.lnk"));
1185 file2.remove();
1186
1187 QTest::addColumn<QString>("path");
1188 QTest::addColumn<bool>("isSymLink");
1189 QTest::addColumn<QString>("linkTarget");
1190
1191 QTest::newRow("existent file") << SRCDIR "tst_qfileinfo.cpp" << false << "";
1192 QTest::newRow("link") << "link.lnk" << true << QFileInfo(SRCDIR "tst_qfileinfo.cpp").absoluteFilePath();
1193 QTest::newRow("broken link") << "brokenlink.lnk" << true << QFileInfo("dummyfile").absoluteFilePath();
1194 #endif
1195 }
1196
isSymLink()1197 void tst_QFileInfo::isSymLink()
1198 {
1199 #ifndef NO_SYMLINKS
1200 QFETCH(QString, path);
1201 QFETCH(bool, isSymLink);
1202 QFETCH(QString, linkTarget);
1203
1204 QFileInfo fi(path);
1205 QCOMPARE(fi.isSymLink(), isSymLink);
1206 QCOMPARE(fi.symLinkTarget(), linkTarget);
1207 #else
1208 QSKIP("no symbolic link support on this platform", SkipAll);
1209 #endif
1210 }
1211
isHidden_data()1212 void tst_QFileInfo::isHidden_data()
1213 {
1214 QTest::addColumn<QString>("path");
1215 QTest::addColumn<bool>("isHidden");
1216 foreach (const QFileInfo& info, QDir::drives()) {
1217 QTest::newRow(qPrintable("drive." + info.path())) << info.path() << false;
1218 }
1219
1220 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
1221 QVERIFY(QDir("./hidden-directory").exists() || QDir().mkdir("./hidden-directory"));
1222 QVERIFY(SetFileAttributesW(reinterpret_cast<LPCWSTR>(QString("./hidden-directory").utf16()),FILE_ATTRIBUTE_HIDDEN));
1223 QTest::newRow("C:/path/to/hidden-directory") << QDir::currentPath() + QString::fromLatin1("/hidden-directory") << true;
1224 QTest::newRow("C:/path/to/hidden-directory/.") << QDir::currentPath() + QString::fromLatin1("/hidden-directory/.") << true;
1225 #endif
1226 #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
1227 QVERIFY(QDir("./.hidden-directory").exists() || QDir().mkdir("./.hidden-directory"));
1228 QTest::newRow("/path/to/.hidden-directory") << QDir::currentPath() + QString("/.hidden-directory") << true;
1229 QTest::newRow("/path/to/.hidden-directory/.") << QDir::currentPath() + QString("/.hidden-directory/.") << true;
1230 QTest::newRow("/path/to/.hidden-directory/..") << QDir::currentPath() + QString("/.hidden-directory/..") << true;
1231 #endif
1232
1233 #if defined(Q_OS_MAC)
1234 // /bin has the hidden attribute on Mac OS X
1235 QTest::newRow("/bin/") << QString::fromLatin1("/bin/") << true;
1236 #elif !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
1237 QTest::newRow("/bin/") << QString::fromLatin1("/bin/") << false;
1238 #endif
1239
1240 #ifdef Q_OS_MAC
1241 QTest::newRow("mac_etc") << QString::fromLatin1("/etc") << true;
1242 QTest::newRow("mac_private_etc") << QString::fromLatin1("/private/etc") << false;
1243 QTest::newRow("mac_Applications") << QString::fromLatin1("/Applications") << false;
1244 #endif
1245
1246 #ifdef Q_OS_SYMBIAN
1247 // No guaranteed hidden file knows to exist in Symbian filesystem, so make one.
1248 QString hiddenFileName("hidden.txt");
1249 QString notHiddenFileName("nothidden.txt");
1250 QTest::newRow("hidden file") << hiddenFileName << true;
1251 QTest::newRow("non-hidden file") << notHiddenFileName << false;
1252
1253 {
1254 QFile file(hiddenFileName);
1255 QVERIFY(file.open(QIODevice::WriteOnly));
1256 QTextStream t(&file);
1257 t << "foobar";
1258
1259 QFile file2(notHiddenFileName);
1260 QVERIFY(file2.open(QIODevice::WriteOnly));
1261 QTextStream t2(&file2);
1262 t2 << "foobar";
1263 }
1264
1265 RFs rfs;
1266 TInt err = rfs.Connect();
1267 QCOMPARE(err, KErrNone);
1268 HBufC* symFile = qt_QString2HBufC(hiddenFileName);
1269 err = rfs.SetAtt(*symFile, KEntryAttHidden, 0);
1270 rfs.Close();
1271 delete symFile;
1272 QCOMPARE(err, KErrNone);
1273 #endif
1274 }
1275
isHidden()1276 void tst_QFileInfo::isHidden()
1277 {
1278 QFETCH(QString, path);
1279 QFETCH(bool, isHidden);
1280 QFileInfo fi(path);
1281
1282 QCOMPARE(fi.isHidden(), isHidden);
1283 }
1284
1285 #if defined(Q_OS_MAC)
isHiddenFromFinder()1286 void tst_QFileInfo::isHiddenFromFinder()
1287 {
1288 const char *filename = "test_foobar.txt";
1289
1290 QFile testFile(filename);
1291 testFile.open(QIODevice::WriteOnly | QIODevice::Append);
1292 testFile.write(QByteArray("world"));
1293 testFile.close();
1294
1295 struct stat buf;
1296 stat(filename, &buf);
1297 chflags(filename, buf.st_flags | UF_HIDDEN);
1298
1299 QFileInfo fi(filename);
1300 QCOMPARE(fi.isHidden(), true);
1301
1302 testFile.remove();
1303 }
1304 #endif
1305
isBundle_data()1306 void tst_QFileInfo::isBundle_data()
1307 {
1308 QTest::addColumn<QString>("path");
1309 QTest::addColumn<bool>("isBundle");
1310 QTest::newRow("root") << QString::fromLatin1("/") << false;
1311 #ifdef Q_OS_MAC
1312 QTest::newRow("mac_Applications") << QString::fromLatin1("/Applications") << false;
1313 QTest::newRow("mac_Applications") << QString::fromLatin1("/Applications/Safari.app") << true;
1314 #endif
1315 }
1316
isBundle()1317 void tst_QFileInfo::isBundle()
1318 {
1319 QFETCH(QString, path);
1320 QFETCH(bool, isBundle);
1321 QFileInfo fi(path);
1322 QCOMPARE(fi.isBundle(), isBundle);
1323 }
1324
isLocalFs_data()1325 void tst_QFileInfo::isLocalFs_data()
1326 {
1327 QTest::addColumn<QString>("path");
1328 QTest::addColumn<bool>("isLocalFs");
1329
1330 QTest::newRow("local root") << QString::fromLatin1("/") << true;
1331 QTest::newRow("local non-existent file") << QString::fromLatin1("/abrakadabra.boo") << true;
1332
1333 QTest::newRow("qresource root") << QString::fromLatin1(":/") << false;
1334 }
1335
isLocalFs()1336 void tst_QFileInfo::isLocalFs()
1337 {
1338 QFETCH(QString, path);
1339 QFETCH(bool, isLocalFs);
1340
1341 QFileInfo info(path);
1342 QFileInfoPrivate *privateInfo = getPrivate(info);
1343 QCOMPARE((privateInfo->fileEngine == 0), isLocalFs);
1344 if (privateInfo->fileEngine)
1345 QCOMPARE(bool(privateInfo->fileEngine->fileFlags(QAbstractFileEngine::LocalDiskFlag)
1346 & QAbstractFileEngine::LocalDiskFlag), isLocalFs);
1347 }
1348
refresh()1349 void tst_QFileInfo::refresh()
1350 {
1351 #if defined(Q_OS_WINCE) || defined(Q_OS_WIN)
1352 int sleepTime = 3000;
1353 #else
1354 int sleepTime = 2000;
1355 #endif
1356
1357 QFile::remove("file1");
1358 QFile file("file1");
1359 QVERIFY(file.open(QFile::WriteOnly));
1360 QCOMPARE(file.write("JAJAJAA"), qint64(7));
1361 file.flush();
1362
1363 QFileInfo info(file);
1364 QDateTime lastModified = info.lastModified();
1365 QCOMPARE(info.size(), qint64(7));
1366
1367 QTest::qSleep(sleepTime);
1368
1369 QCOMPARE(file.write("JOJOJO"), qint64(6));
1370 file.flush();
1371 QVERIFY(info.lastModified() == lastModified);
1372
1373 QCOMPARE(info.size(), qint64(7));
1374 #if defined(Q_OS_WIN) || defined(Q_OS_WINCE)
1375 if (QSysInfo::windowsVersion() & QSysInfo::WV_VISTA ||
1376 QSysInfo::windowsVersion() & QSysInfo::WV_CE_based)
1377 file.close();
1378 #endif
1379 #if defined(Q_OS_WINCE)
1380 // On Windows CE we need to close the file.
1381 // Otherwise the content will be cached and not
1382 // flushed to the storage, although we flushed it
1383 // manually!!! CE has interim cache, we cannot influence.
1384 QTest::qWait(5000);
1385 #endif
1386 info.refresh();
1387 QCOMPARE(info.size(), qint64(13));
1388 QVERIFY(info.lastModified() > lastModified);
1389
1390 QFileInfo info2 = info;
1391 QCOMPARE(info2.size(), info.size());
1392
1393 info2.refresh();
1394 QCOMPARE(info2.size(), info.size());
1395 }
1396
1397 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
ntfsJunctionPointsAndSymlinks_data()1398 void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data()
1399 {
1400 QTest::addColumn<QString>("path");
1401 QTest::addColumn<bool>("isSymLink");
1402 QTest::addColumn<QString>("linkTarget");
1403 QTest::addColumn<QString>("canonicalFilePath");
1404
1405 QDir pwd;
1406 pwd.mkdir("target");
1407
1408 QLibrary kernel32("kernel32");
1409 typedef BOOLEAN (WINAPI *PtrCreateSymbolicLink)(LPCWSTR, LPCWSTR, DWORD);
1410 PtrCreateSymbolicLink createSymbolicLinkW = 0;
1411 createSymbolicLinkW = (PtrCreateSymbolicLink) kernel32.resolve("CreateSymbolicLinkW");
1412 if (!createSymbolicLinkW) {
1413 //we need at least one data set for the test not to fail when skipping _data function
1414 QDir target("target");
1415 QTest::newRow("dummy") << target.path() << false << "" << target.canonicalPath();
1416 QSKIP("symbolic links not supported by operating system",SkipSingle);
1417 }
1418 {
1419 //Directory symlinks
1420 QDir target("target");
1421 QVERIFY(target.exists());
1422
1423 QString absTarget = QDir::toNativeSeparators(target.absolutePath());
1424 QString absSymlink = QDir::toNativeSeparators(pwd.absolutePath()).append("\\abs_symlink");
1425 QString relTarget = "target";
1426 QString relSymlink = "rel_symlink";
1427 QString fileInTarget(absTarget);
1428 fileInTarget.append("\\file");
1429 QString fileInSymlink(absSymlink);
1430 fileInSymlink.append("\\file");
1431 QFile file(fileInTarget);
1432 file.open(QIODevice::ReadWrite);
1433 file.close();
1434
1435 DWORD err = ERROR_SUCCESS ;
1436 if (!pwd.exists("abs_symlink"))
1437 if (!createSymbolicLinkW((wchar_t*)absSymlink.utf16(),(wchar_t*)absTarget.utf16(),0x1))
1438 err = GetLastError();
1439 if (err == ERROR_SUCCESS && !pwd.exists(relSymlink))
1440 if (!createSymbolicLinkW((wchar_t*)relSymlink.utf16(),(wchar_t*)relTarget.utf16(),0x1))
1441 err = GetLastError();
1442 if (err != ERROR_SUCCESS) {
1443 wchar_t errstr[0x100];
1444 DWORD count = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
1445 0, err, 0, errstr, 0x100, 0);
1446 QString error(QString::fromWCharArray (errstr, count));
1447 qWarning() << error;
1448 //we need at least one data set for the test not to assert fail when skipping _data function
1449 QDir target("target");
1450 QTest::newRow("dummy") << target.path() << false << "" << target.canonicalPath();
1451 QSKIP("link not supported by FS or insufficient privilege", SkipSingle);
1452 }
1453 QVERIFY(file.exists());
1454
1455 QTest::newRow("absolute dir symlink") << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalPath();
1456 QTest::newRow("relative dir symlink") << relSymlink << true << QDir::fromNativeSeparators(relTarget) << target.canonicalPath();
1457 QTest::newRow("file in symlink dir") << fileInSymlink << false << "" << target.canonicalPath().append("/file");
1458 }
1459 {
1460 //File symlinks
1461 QFileInfo target(SRCDIR "tst_qfileinfo.cpp");
1462 QString absTarget = QDir::toNativeSeparators(target.absoluteFilePath());
1463 QString absSymlink = QDir::toNativeSeparators(pwd.absolutePath()).append("\\abs_symlink.cpp");
1464 QString relTarget = QDir::toNativeSeparators(pwd.relativeFilePath(target.absoluteFilePath()));
1465 QString relSymlink = "rel_symlink.cpp";
1466 QVERIFY(pwd.exists("abs_symlink.cpp") || createSymbolicLinkW((wchar_t*)absSymlink.utf16(),(wchar_t*)absTarget.utf16(),0x0));
1467 QVERIFY(pwd.exists(relSymlink) || createSymbolicLinkW((wchar_t*)relSymlink.utf16(),(wchar_t*)relTarget.utf16(),0x0));
1468
1469 QTest::newRow("absolute file symlink") << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath();
1470 QTest::newRow("relative file symlink") << relSymlink << true << QDir::fromNativeSeparators(relTarget) << target.canonicalFilePath();
1471 }
1472
1473 //Junctions
1474 QString target = "target";
1475 QString junction = "junction_pwd";
1476 FileSystem::createNtfsJunction(target, junction);
1477 QFileInfo targetInfo(target);
1478 QTest::newRow("junction_pwd") << junction << false << QString() << QString();
1479
1480 QFileInfo fileInJunction(targetInfo.absoluteFilePath().append("/file"));
1481 QFile file(fileInJunction.absoluteFilePath());
1482 file.open(QIODevice::ReadWrite);
1483 file.close();
1484 QVERIFY(file.exists());
1485 QTest::newRow("file in junction") << fileInJunction.absoluteFilePath() << false << "" << fileInJunction.canonicalFilePath();
1486
1487 target = QDir::rootPath();
1488 junction = "junction_root";
1489 FileSystem::createNtfsJunction(target, junction);
1490 targetInfo.setFile(target);
1491 QTest::newRow("junction_root") << junction << false << QString() << QString();
1492
1493 //Mountpoint
1494 typedef BOOLEAN (WINAPI *PtrGetVolumeNameForVolumeMountPointW)(LPCWSTR, LPWSTR, DWORD);
1495 PtrGetVolumeNameForVolumeMountPointW getVolumeNameForVolumeMountPointW = 0;
1496 getVolumeNameForVolumeMountPointW = (PtrGetVolumeNameForVolumeMountPointW) kernel32.resolve("GetVolumeNameForVolumeMountPointW");
1497 if(getVolumeNameForVolumeMountPointW)
1498 {
1499 wchar_t buffer[MAX_PATH];
1500 QString rootPath = QDir::toNativeSeparators(QDir::rootPath());
1501 QVERIFY(getVolumeNameForVolumeMountPointW((wchar_t*)rootPath.utf16(), buffer, MAX_PATH));
1502 QString rootVolume = QString::fromWCharArray(buffer);
1503 junction = "mountpoint";
1504 rootVolume.replace("\\\\?\\","\\??\\");
1505 FileSystem::createNtfsJunction(rootVolume, junction);
1506 QTest::newRow("mountpoint") << junction << false << QString() << QString();
1507 }
1508 }
1509
ntfsJunctionPointsAndSymlinks()1510 void tst_QFileInfo::ntfsJunctionPointsAndSymlinks()
1511 {
1512 QFETCH(QString, path);
1513 QFETCH(bool, isSymLink);
1514 QFETCH(QString, linkTarget);
1515 QFETCH(QString, canonicalFilePath);
1516
1517 QFileInfo fi(path);
1518 QCOMPARE(fi.isSymLink(), isSymLink);
1519 if (isSymLink) {
1520 QCOMPARE(fi.symLinkTarget(), linkTarget);
1521 QCOMPARE(fi.canonicalFilePath(), canonicalFilePath);
1522 }
1523 }
1524
brokenShortcut()1525 void tst_QFileInfo::brokenShortcut()
1526 {
1527 QString linkName("borkenlink.lnk");
1528 QFile::remove(linkName);
1529 QFile file(linkName);
1530 file.open(QFile::WriteOnly);
1531 file.write("b0rk");
1532 file.close();
1533
1534 QFileInfo info(linkName);
1535 QVERIFY(info.isSymLink());
1536 QVERIFY(!info.exists());
1537 QFile::remove(linkName);
1538
1539 QDir current; // QTBUG-21863
1540 QVERIFY(current.mkdir(linkName));
1541 QFileInfo dirInfo(linkName);
1542 QVERIFY(!dirInfo.isSymLink());
1543 QVERIFY(dirInfo.isDir());
1544 current.rmdir(linkName);
1545 }
1546 #endif
1547
isWritable()1548 void tst_QFileInfo::isWritable()
1549 {
1550 QFile tempfile("tempfile.txt");
1551 tempfile.open(QIODevice::WriteOnly);
1552 tempfile.write("This file is generated by the QFileInfo autotest.");
1553 tempfile.close();
1554
1555 QVERIFY(QFileInfo("tempfile.txt").isWritable());
1556 tempfile.remove();
1557
1558 #ifdef Q_OS_WIN
1559 #ifdef Q_OS_WINCE
1560 QFileInfo fi("\\Windows\\wince.nls");
1561 #else
1562 QFileInfo fi("c:\\pagefile.sys");
1563 #endif
1564 QVERIFY(fi.exists());
1565 QVERIFY(!fi.isWritable());
1566 #endif
1567 #if defined (Q_OS_BLACKBERRY)
1568 // The Blackberry filesystem is read-only
1569 QVERIFY(!QFileInfo("/etc/passwd").isWritable());
1570 #elif defined (Q_OS_UNIX) && !defined (Q_OS_SYMBIAN)
1571 if (::getuid() == 0)
1572 QVERIFY(QFileInfo("/etc/passwd").isWritable());
1573 else
1574 QVERIFY(!QFileInfo("/etc/passwd").isWritable());
1575 #endif
1576 }
1577
isExecutable()1578 void tst_QFileInfo::isExecutable()
1579 {
1580 #ifdef Q_OS_SYMBIAN
1581 QString appPath = "c:/sys/bin/tst_qfileinfo.exe";
1582 #else
1583 QString appPath = QCoreApplication::applicationDirPath();
1584 appPath += "/tst_qfileinfo";
1585 # if defined(Q_OS_WIN)
1586 appPath += ".exe";
1587 # endif
1588 #endif
1589 QFileInfo fi(appPath);
1590 QCOMPARE(fi.isExecutable(), true);
1591
1592 QCOMPARE(QFileInfo("qfileinfo.pro").isExecutable(), false);
1593 }
1594
1595
testDecomposedUnicodeNames_data()1596 void tst_QFileInfo::testDecomposedUnicodeNames_data()
1597 {
1598 QTest::addColumn<QString>("filePath");
1599 QTest::addColumn<QString>("fileName");
1600 QTest::addColumn<bool>("exists");
1601 QString currPath = QDir::currentPath();
1602 QTest::newRow("latin-only") << currPath + "/4.pdf" << "4.pdf" << true;
1603 QTest::newRow("one-decomposed uni") << currPath + QString::fromUtf8("/4 ä.pdf") << QString::fromUtf8("4 ä.pdf") << true;
1604 QTest::newRow("many-decomposed uni") << currPath + QString::fromUtf8("/4 äääcopy.pdf") << QString::fromUtf8("4 äääcopy.pdf") << true;
1605 QTest::newRow("no decomposed") << currPath + QString::fromUtf8("/4 øøøcopy.pdf") << QString::fromUtf8("4 øøøcopy.pdf") << true;
1606 }
1607
createFileNative(const QString & filePath)1608 static void createFileNative(const QString &filePath)
1609 {
1610 #ifdef Q_OS_UNIX
1611 int fd = open(filePath.normalized(QString::NormalizationForm_D).toUtf8().constData(), O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1612 if (fd < 0) {
1613 QFAIL("couldn't create file");
1614 } else {
1615 close(fd);
1616 }
1617 #else
1618 Q_UNUSED(filePath);
1619 #endif
1620 }
1621
removeFileNative(const QString & filePath)1622 static void removeFileNative(const QString &filePath)
1623 {
1624 #ifdef Q_OS_UNIX
1625 unlink(filePath.normalized(QString::NormalizationForm_D).toUtf8().constData());
1626 #else
1627 Q_UNUSED(filePath);
1628 #endif
1629 }
1630
testDecomposedUnicodeNames()1631 void tst_QFileInfo::testDecomposedUnicodeNames()
1632 {
1633 #ifndef Q_OS_MAC
1634 QSKIP("This is a OS X only test (unless you know more about filesystems, then maybe you should try it ;)", SkipAll);
1635 #endif
1636 QFETCH(QString, filePath);
1637 createFileNative(filePath);
1638
1639 QFileInfo file(filePath);
1640 QTEST(file.fileName(), "fileName");
1641 QTEST(file.exists(), "exists");
1642 removeFileNative(filePath);
1643 }
1644
equalOperator() const1645 void tst_QFileInfo::equalOperator() const
1646 {
1647 /* Compare two default constructed values. Yes, to me it seems it should be the opposite too, but
1648 * this is how the code was written. */
1649 QVERIFY(!(QFileInfo() == QFileInfo()));
1650 }
1651
1652
equalOperatorWithDifferentSlashes() const1653 void tst_QFileInfo::equalOperatorWithDifferentSlashes() const
1654 {
1655 const QFileInfo fi1("/usr");
1656 const QFileInfo fi2("/usr/");
1657
1658 QCOMPARE(fi1, fi2);
1659 }
1660
notEqualOperator() const1661 void tst_QFileInfo::notEqualOperator() const
1662 {
1663 /* Compare two default constructed values. Yes, to me it seems it should be the opposite too, but
1664 * this is how the code was written. */
1665 QVERIFY(QFileInfo() != QFileInfo());
1666 }
1667
detachingOperations()1668 void tst_QFileInfo::detachingOperations()
1669 {
1670 QFileInfo info1;
1671 QVERIFY(info1.caching());
1672 info1.setCaching(false);
1673
1674 {
1675 QFileInfo info2 = info1;
1676
1677 QVERIFY(!info1.caching());
1678 QVERIFY(!info2.caching());
1679
1680 info2.setCaching(true);
1681 QVERIFY(info2.caching());
1682
1683 info1.setFile("foo");
1684 QVERIFY(!info1.caching());
1685 }
1686
1687 {
1688 QFile file("foo");
1689 info1.setFile(file);
1690 QVERIFY(!info1.caching());
1691 }
1692
1693 info1.setFile(QDir(), "foo");
1694 QVERIFY(!info1.caching());
1695
1696 {
1697 QFileInfo info3;
1698 QVERIFY(info3.caching());
1699
1700 info3 = info1;
1701 QVERIFY(!info3.caching());
1702 }
1703
1704 info1.refresh();
1705 QVERIFY(!info1.caching());
1706
1707 QVERIFY(info1.makeAbsolute());
1708 QVERIFY(!info1.caching());
1709
1710 info1.detach();
1711 QVERIFY(!info1.caching());
1712 }
1713
1714 #if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
1715 #if defined (Q_OS_WIN)
IsUserAdmin()1716 BOOL IsUserAdmin()
1717 {
1718 BOOL b;
1719 SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
1720 PSID AdministratorsGroup;
1721 b = AllocateAndInitializeSid(
1722 &NtAuthority,
1723 2,
1724 SECURITY_BUILTIN_DOMAIN_RID,
1725 DOMAIN_ALIAS_RID_ADMINS,
1726 0, 0, 0, 0, 0, 0,
1727 &AdministratorsGroup);
1728 if (b) {
1729 if (!CheckTokenMembership( NULL, AdministratorsGroup, &b))
1730 b = FALSE;
1731 FreeSid(AdministratorsGroup);
1732 }
1733
1734 return(b);
1735 }
1736 #endif
1737
owner()1738 void tst_QFileInfo::owner()
1739 {
1740 QString userName;
1741 #if defined(Q_OS_UNIX)
1742 {
1743 passwd *user = getpwuid(geteuid());
1744 QVERIFY(user);
1745 char *usernameBuf = user->pw_name;
1746 userName = QString::fromLocal8Bit(usernameBuf);
1747 }
1748 #endif
1749 #if defined(Q_OS_WIN)
1750 wchar_t usernameBuf[1024];
1751 DWORD bufSize = 1024;
1752 if (GetUserNameW(usernameBuf, &bufSize)) {
1753 userName = QString::fromWCharArray(usernameBuf);
1754 if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && IsUserAdmin()) {
1755 // Special case : If the user is a member of Administrators group, all files
1756 // created by the current user are owned by the Administrators group.
1757 LPLOCALGROUP_USERS_INFO_0 pBuf = NULL;
1758 DWORD dwLevel = 0;
1759 DWORD dwFlags = LG_INCLUDE_INDIRECT ;
1760 DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;
1761 DWORD dwEntriesRead = 0;
1762 DWORD dwTotalEntries = 0;
1763 NET_API_STATUS nStatus;
1764 nStatus = NetUserGetLocalGroups(0, usernameBuf, dwLevel, dwFlags, (LPBYTE *) &pBuf,
1765 dwPrefMaxLen, &dwEntriesRead, &dwTotalEntries);
1766 // Check if the current user is a member of Administrators group
1767 if (nStatus == NERR_Success && pBuf){
1768 for (int i = 0; i < (int)dwEntriesRead; i++) {
1769 QString groupName = QString::fromWCharArray(pBuf[i].lgrui0_name);
1770 if (!groupName.compare(QLatin1String("Administrators")))
1771 userName = groupName;
1772 }
1773 }
1774 if (pBuf != NULL)
1775 NetApiBufferFree(pBuf);
1776 }
1777 }
1778 extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;
1779 qt_ntfs_permission_lookup = 1;
1780 #endif
1781 if (userName.isEmpty())
1782 QSKIP("Can't retrieve the user name", SkipAll);
1783 QString fileName("ownertest.txt");
1784 QVERIFY(!QFile::exists(fileName) || QFile::remove(fileName));
1785 {
1786 QFile testFile(fileName);
1787 QVERIFY(testFile.open(QIODevice::WriteOnly | QIODevice::Text));
1788 QByteArray testData("testfile");
1789 QVERIFY(testFile.write(testData) != -1);
1790 }
1791 QFileInfo fi(fileName);
1792 QVERIFY(fi.exists());
1793 QCOMPARE(fi.owner(), userName);
1794
1795 QFile::remove(fileName);
1796 #if defined(Q_OS_WIN)
1797 qt_ntfs_permission_lookup = 0;
1798 #endif
1799 }
1800 #endif
1801
group()1802 void tst_QFileInfo::group()
1803 {
1804 QString expected;
1805 #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
1806 struct group *gr;
1807 gid_t gid = getegid();
1808 gr = getgrgid(gid);
1809 expected = QString::fromLocal8Bit(gr->gr_name);
1810 #endif
1811
1812 QString fileName("ownertest.txt");
1813 if (QFile::exists(fileName))
1814 QFile::remove(fileName);
1815 QFile testFile(fileName);
1816 QVERIFY(testFile.open(QIODevice::WriteOnly | QIODevice::Text));
1817 QByteArray testData("testfile");
1818 QVERIFY(testFile.write(testData) != -1);
1819 testFile.close();
1820 QFileInfo fi(fileName);
1821 QVERIFY(fi.exists());
1822
1823 QCOMPARE(fi.group(), expected);
1824 }
1825
invalidState()1826 void tst_QFileInfo::invalidState()
1827 {
1828 // Shouldn't crash;
1829
1830 {
1831 QFileInfo info;
1832 QCOMPARE(info.size(), qint64(0));
1833 QVERIFY(!info.exists());
1834
1835 info.setCaching(false);
1836
1837 info.created();
1838 info.lastRead();
1839 info.lastModified();
1840 }
1841
1842 {
1843 QFileInfo info("");
1844 QCOMPARE(info.size(), qint64(0));
1845 QVERIFY(!info.exists());
1846
1847 info.setCaching(false);
1848
1849 info.created();
1850 info.lastRead();
1851 info.lastModified();
1852 }
1853
1854 {
1855 QFileInfo info("file-doesn't-really-exist.txt");
1856 QCOMPARE(info.size(), qint64(0));
1857 QVERIFY(!info.exists());
1858
1859 info.setCaching(false);
1860
1861 info.created();
1862 info.lastRead();
1863 info.lastModified();
1864 }
1865
1866 QVERIFY(true);
1867 }
1868
1869 QTEST_MAIN(tst_QFileInfo)
1870 #include "tst_qfileinfo.moc"
1871