2 * SPDX-FileCopyrightText: 2012 Peter Penz <peter.penz19@gmail.com>
4 * SPDX-License-Identifier: GPL-2.0-or-later
7 #include "views/viewproperties.h"
8 #include "dolphin_generalsettings.h"
11 #include <KFileMetaData/UserMetaData>
13 #include <QStorageInfo>
16 class ViewPropertiesTest
: public QObject
25 void testReadOnlyBehavior();
26 void testReadOnlyDirectory();
28 void testParamMigrationToFileAttr();
29 void testParamMigrationToFileAttrKeepDirectory();
30 void testExtendedAttributeFull();
31 void testUseAsDefaultViewSettings();
34 bool m_globalViewProps
;
38 void ViewPropertiesTest::initTestCase()
40 QStandardPaths::setTestModeEnabled(true);
42 GeneralSettings::self()->setViewPropsTimestamp(QDateTime::currentDateTime());
43 QVERIFY(GeneralSettings::self()->save());
46 void ViewPropertiesTest::init()
48 m_globalViewProps
= GeneralSettings::self()->globalViewProps();
49 GeneralSettings::self()->setGlobalViewProps(false);
50 GeneralSettings::self()->save();
52 // It is mandatory to create the test-directory inside the home-directory
53 // of the user: ViewProperties does not write inside directories
54 // outside the home-directory to prevent overwriting other user-settings
55 // in case if write-permissions are given.
56 m_testDir
= new TestDir(QDir::homePath() + "/.viewPropertiesTest-");
59 void ViewPropertiesTest::cleanup()
64 GeneralSettings::self()->setGlobalViewProps(m_globalViewProps
);
65 GeneralSettings::self()->save();
69 * Test whether only reading properties won't result in creating
70 * a .directory file when destructing the ViewProperties instance
71 * and autosaving is enabled.
73 void ViewPropertiesTest::testReadOnlyBehavior()
75 QString dotDirectoryFile
= m_testDir
->url().toLocalFile() + "/.directory";
76 QVERIFY(!QFile::exists(dotDirectoryFile
));
78 QScopedPointer
<ViewProperties
> props(new ViewProperties(m_testDir
->url()));
79 QVERIFY(props
->isAutoSaveEnabled());
80 const QByteArray sortRole
= props
->sortRole();
84 QVERIFY(!QFile::exists(dotDirectoryFile
));
87 void ViewPropertiesTest::testReadOnlyDirectory()
89 const QUrl testDirUrl
= m_testDir
->url();
90 const QString localFolder
= testDirUrl
.toLocalFile();
91 const QString dotDirectoryFile
= localFolder
+ "/.directory";
92 QVERIFY(!QFile::exists(dotDirectoryFile
));
94 // restrict write permissions
95 QVERIFY(QFile(localFolder
).setPermissions(QFileDevice::ReadOwner
));
97 QScopedPointer
<ViewProperties
> props(new ViewProperties(testDirUrl
));
98 const QString destinationDir
= props
->destinationDir(QStringLiteral("local")) + localFolder
;
100 QVERIFY(props
->isAutoSaveEnabled());
101 props
->setSortRole("someNewSortRole");
104 qDebug() << destinationDir
;
105 QVERIFY(QDir(destinationDir
).exists());
107 QVERIFY(!QFile::exists(dotDirectoryFile
));
108 KFileMetaData::UserMetaData
metadata(localFolder
);
109 const QString viewProperties
= metadata
.attribute(QStringLiteral("kde.fm.viewproperties#1"));
110 QVERIFY(viewProperties
.isEmpty());
112 props
.reset(new ViewProperties(testDirUrl
));
113 QVERIFY(props
->isAutoSaveEnabled());
114 QCOMPARE(props
->sortRole(), "someNewSortRole");
117 metadata
= KFileMetaData::UserMetaData(destinationDir
);
118 if (metadata
.isSupported()) {
119 QVERIFY(metadata
.hasAttribute("kde.fm.viewproperties#1"));
121 QVERIFY(QFile::exists(destinationDir
+ "/.directory"));
124 // un-restrict write permissions
125 QFile(localFolder
).setPermissions(QFileDevice::ReadOwner
| QFileDevice::WriteOwner
);
128 void ViewPropertiesTest::testAutoSave()
130 QString dotDirectoryFile
= m_testDir
->url().toLocalFile() + "/.directory";
131 QVERIFY(!QFile::exists(dotDirectoryFile
));
133 QScopedPointer
<ViewProperties
> props(new ViewProperties(m_testDir
->url()));
134 QVERIFY(props
->isAutoSaveEnabled());
135 props
->setSortRole("someNewSortRole");
138 KFileMetaData::UserMetaData
metadata(m_testDir
->url().toLocalFile());
139 if (metadata
.isSupported()) {
140 auto viewProperties
= metadata
.attribute(QStringLiteral("kde.fm.viewproperties#1"));
141 QVERIFY(!viewProperties
.isEmpty());
142 QVERIFY(!QFile::exists(dotDirectoryFile
));
144 QVERIFY(QFile::exists(dotDirectoryFile
));
148 void ViewPropertiesTest::testParamMigrationToFileAttr()
150 QString dotDirectoryFilePath
= m_testDir
->url().toLocalFile() + "/.directory";
151 QVERIFY(!QFile::exists(dotDirectoryFilePath
));
153 const char *settingsContent
= R
"SETTINGS("
157 Timestamp
=2023,12,29,10,44,15.793
158 VisibleRoles
=text
,CustomizedDetails
,Details_text
,Details_modificationtime
,Details_type
161 HiddenFilesShown
=true)SETTINGS
";
162 auto dotDirectoryFile = QFile(dotDirectoryFilePath);
163 QVERIFY(dotDirectoryFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate));
164 QTextStream out(&dotDirectoryFile);
165 out << settingsContent;
166 dotDirectoryFile.close();
168 KFileMetaData::UserMetaData metadata(m_testDir->url().toLocalFile());
170 QScopedPointer<ViewProperties> props(new ViewProperties(m_testDir->url()));
171 QCOMPARE(props->viewMode(), DolphinView::Mode::DetailsView);
172 QVERIFY(props->hiddenFilesShown());
175 if (metadata.isSupported()) {
176 auto viewProperties = metadata.attribute(QStringLiteral("kde
.fm
.viewproperties
#1"));
177 QVERIFY(!viewProperties.isEmpty());
178 QVERIFY(!QFile::exists(dotDirectoryFilePath));
180 QVERIFY(QFile::exists(dotDirectoryFilePath));
184 ViewProperties props(m_testDir->url());
185 QCOMPARE(props.viewMode(), DolphinView::Mode::DetailsView);
186 QVERIFY(props.hiddenFilesShown());
189 void ViewPropertiesTest::testParamMigrationToFileAttrKeepDirectory()
191 QString dotDirectoryFilePath = m_testDir->url().toLocalFile() + "/.directory";
192 QVERIFY(!QFile::exists(dotDirectoryFilePath));
194 const char *settingsContent = R"SETTINGS("
198 Timestamp=2023,12,29,10,44,15.793
199 VisibleRoles=text,CustomizedDetails,Details_text,Details_modificationtime,Details_type
202 HiddenFilesShown=true
205 ThoseShouldBeKept=true
207 auto dotDirectoryFile
= QFile(dotDirectoryFilePath
);
208 QVERIFY(dotDirectoryFile
.open(QIODevice::WriteOnly
| QIODevice::Text
| QIODevice::Truncate
));
209 QTextStream
out(&dotDirectoryFile
);
210 out
<< settingsContent
;
211 dotDirectoryFile
.close();
213 KFileMetaData::UserMetaData
metadata(m_testDir
->url().toLocalFile());
215 QScopedPointer
<ViewProperties
> props(new ViewProperties(m_testDir
->url()));
216 QCOMPARE(props
->viewMode(), DolphinView::Mode::DetailsView
);
217 QVERIFY(props
->hiddenFilesShown());
220 if (metadata
.isSupported()) {
221 auto viewProperties
= metadata
.attribute(QStringLiteral("kde.fm.viewproperties#1"));
222 QVERIFY(!viewProperties
.isEmpty());
225 QVERIFY(QFile::exists(dotDirectoryFilePath
));
226 KConfig
directorySettings(dotDirectoryFilePath
, KConfig::SimpleConfig
);
227 QCOMPARE(directorySettings
.groupList(), {"Other"});
230 ViewProperties
props(m_testDir
->url());
231 QVERIFY(props
.hiddenFilesShown());
232 QCOMPARE(props
.viewMode(), DolphinView::Mode::DetailsView
);
234 QVERIFY(QFile::exists(dotDirectoryFilePath
));
237 void ViewPropertiesTest::testExtendedAttributeFull()
240 QSKIP("Only unix is supported, for this test");
242 QString dotDirectoryFile
= m_testDir
->url().toLocalFile() + "/.directory";
243 QVERIFY(!QFile::exists(dotDirectoryFile
));
245 KFileMetaData::UserMetaData
metadata(m_testDir
->url().toLocalFile());
246 if (!metadata
.isSupported()) {
247 QSKIP("need extended attribute/filesystem metadata to be usefull");
250 QStorageInfo
storageInfo(m_testDir
->url().toLocalFile());
251 auto blockSize
= storageInfo
.blockSize();
253 KFileMetaData::UserMetaData::Error result
;
254 // write a close to block size theorical maximum size for attributes in Linux for ext4
255 // and btrfs (4Kib typically) when ReiserFS/XFS allow XATTR_SIZE_MAX (64Kib)
256 result
= metadata
.setAttribute("data", QString(blockSize
- 50, 'a'));
257 if (result
!= KFileMetaData::UserMetaData::NoSpace
) {
258 QSKIP("File system supports metadata bigger than file system block size");
261 // write a close to 4k attribute, maximum size in Linux for ext4
262 // so next writing the file metadata fails
263 result
= metadata
.setAttribute("data", QString(blockSize
- 60, 'a'));
264 QCOMPARE(result
, KFileMetaData::UserMetaData::NoError
);
266 QScopedPointer
<ViewProperties
> props(new ViewProperties(m_testDir
->url()));
267 QVERIFY(props
->isAutoSaveEnabled());
268 props
->setSortRole("someNewSortRole");
271 if (metadata
.isSupported()) {
272 auto viewProperties
= metadata
.attribute(QStringLiteral("kde.fm.viewproperties#1"));
273 QVERIFY(viewProperties
.isEmpty());
274 QVERIFY(QFile::exists(dotDirectoryFile
));
276 QFile
dotDirectory(dotDirectoryFile
);
277 KConfig
viewSettings(dotDirectoryFile
, KConfig::SimpleConfig
);
278 QCOMPARE(viewSettings
.groupList(), {"Dolphin"});
279 QCOMPARE(viewSettings
.group("Dolphin").readEntry("SortRole"), "someNewSortRole");
281 QVERIFY(QFile::exists(dotDirectoryFile
));
285 void ViewPropertiesTest::testUseAsDefaultViewSettings()
287 // Create new test directory for this test to make sure the settings are defaults
288 auto testDir
= new TestDir(QDir::homePath() + "/.viewPropertiesTest-");
289 auto cleanupTestDir
= qScopeGuard([testDir
] {
293 // Create a global viewproperties folder
294 QUrl globalPropertiesPath
=
295 QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation
).append("/view_properties/").append(QStringLiteral("global")));
296 QVERIFY(QDir().mkpath(globalPropertiesPath
.toLocalFile()));
297 auto cleanupGlobalDir
= qScopeGuard([globalPropertiesPath
] {
298 QDir().rmdir(globalPropertiesPath
.toLocalFile());
300 ViewProperties
globalProps(globalPropertiesPath
);
302 // Check that theres no .directory file and metadata is supported
303 QString dotDirectoryFile
= testDir
->url().toLocalFile() + "/.directory";
304 QVERIFY(!QFile::exists(dotDirectoryFile
));
305 KFileMetaData::UserMetaData
testDirMetadata(testDir
->url().toLocalFile());
306 KFileMetaData::UserMetaData
globalDirMetadata(globalPropertiesPath
.toLocalFile());
307 if (!testDirMetadata
.isSupported()) {
308 QSKIP("need extended attribute/filesystem metadata to be usefull");
311 const auto newDefaultViewMode
= DolphinView::Mode::DetailsView
;
313 // Equivalent of useAsDefault in ViewPropertiesDialog
314 // This sets the DetailsView as default viewMode
315 GeneralSettings::setGlobalViewProps(true);
316 globalProps
.setViewMode(newDefaultViewMode
);
317 globalProps
.setDirProperties(globalProps
);
319 GeneralSettings::setGlobalViewProps(false);
322 QScopedPointer
<ViewProperties
> globalDirProperties(new ViewProperties(globalPropertiesPath
));
323 auto defaultData
= globalDirProperties
.data();
326 QScopedPointer
<ViewProperties
> testDirProperties(new ViewProperties(testDir
->url()));
327 auto testData
= testDirProperties
.data();
329 // Make sure globalDirProperties are not empty, so they will be used
330 auto globalDirPropString
= globalDirMetadata
.attribute(QStringLiteral("kde.fm.viewproperties#1"));
331 QVERIFY(!globalDirPropString
.isEmpty());
333 // Make sure testDirProperties is empty, so default values are used for it
334 auto testDirPropString
= testDirMetadata
.attribute(QStringLiteral("kde.fm.viewproperties#1"));
335 QVERIFY(testDirPropString
.isEmpty());
337 // Compare that default and new folder viewMode is the new default
338 QCOMPARE(defaultData
->viewMode(), newDefaultViewMode
);
339 QCOMPARE(testData
->viewMode(), defaultData
->viewMode());
342 QTEST_GUILESS_MAIN(ViewPropertiesTest
)
344 #include "viewpropertiestest.moc"