]> cloud.milkyroute.net Git - dolphin.git/blob - src/tests/viewpropertiestest.cpp
Add Filelight menu to Tools menu
[dolphin.git] / src / tests / viewpropertiestest.cpp
1 /*
2 * SPDX-FileCopyrightText: 2012 Peter Penz <peter.penz19@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "views/viewproperties.h"
8 #include "dolphin_generalsettings.h"
9 #include "testdir.h"
10
11 #include <KFileMetaData/UserMetaData>
12
13 #include <QStorageInfo>
14 #include <QTest>
15
16 class ViewPropertiesTest : public QObject
17 {
18 Q_OBJECT
19
20 private Q_SLOTS:
21 void initTestCase();
22 void init();
23 void cleanup();
24
25 void testReadOnlyBehavior();
26 void testReadOnlyDirectory();
27 void testAutoSave();
28 void testParamMigrationToFileAttr();
29 void testParamMigrationToFileAttrKeepDirectory();
30 void testExtendedAttributeFull();
31 void testUseAsDefaultViewSettings();
32 void testUseAsCustomDefaultViewSettings();
33
34 private:
35 bool m_globalViewProps;
36 TestDir *m_testDir;
37 };
38
39 void ViewPropertiesTest::initTestCase()
40 {
41 QStandardPaths::setTestModeEnabled(true);
42
43 GeneralSettings::self()->setViewPropsTimestamp(QDateTime::currentDateTime());
44 QVERIFY(GeneralSettings::self()->save());
45 }
46
47 void ViewPropertiesTest::init()
48 {
49 m_globalViewProps = GeneralSettings::self()->globalViewProps();
50 GeneralSettings::self()->setGlobalViewProps(false);
51 GeneralSettings::self()->save();
52
53 // It is mandatory to create the test-directory inside the home-directory
54 // of the user: ViewProperties does not write inside directories
55 // outside the home-directory to prevent overwriting other user-settings
56 // in case if write-permissions are given.
57 m_testDir = new TestDir(QDir::homePath() + "/.viewPropertiesTest-");
58 }
59
60 void ViewPropertiesTest::cleanup()
61 {
62 delete m_testDir;
63 m_testDir = nullptr;
64
65 GeneralSettings::self()->setGlobalViewProps(m_globalViewProps);
66 GeneralSettings::self()->save();
67 }
68
69 /**
70 * Test whether only reading properties won't result in creating
71 * a .directory file when destructing the ViewProperties instance
72 * and autosaving is enabled.
73 */
74 void ViewPropertiesTest::testReadOnlyBehavior()
75 {
76 QString dotDirectoryFile = m_testDir->url().toLocalFile() + "/.directory";
77 QVERIFY(!QFile::exists(dotDirectoryFile));
78
79 QScopedPointer<ViewProperties> props(new ViewProperties(m_testDir->url()));
80 QVERIFY(props->isAutoSaveEnabled());
81 const QByteArray sortRole = props->sortRole();
82 Q_UNUSED(sortRole)
83 props.reset();
84
85 QVERIFY(!QFile::exists(dotDirectoryFile));
86 }
87
88 void ViewPropertiesTest::testReadOnlyDirectory()
89 {
90 const QUrl testDirUrl = m_testDir->url();
91 const QString localFolder = testDirUrl.toLocalFile();
92 const QString dotDirectoryFile = localFolder + "/.directory";
93 QVERIFY(!QFile::exists(dotDirectoryFile));
94
95 // restrict write permissions
96 QVERIFY(QFile(localFolder).setPermissions(QFileDevice::ReadOwner));
97
98 QScopedPointer<ViewProperties> props(new ViewProperties(testDirUrl));
99 const QString destinationDir = props->destinationDir(QStringLiteral("local")) + localFolder;
100
101 QVERIFY(props->isAutoSaveEnabled());
102 props->setSortRole("someNewSortRole");
103 props.reset();
104
105 qDebug() << destinationDir;
106 QVERIFY(QDir(destinationDir).exists());
107
108 QVERIFY(!QFile::exists(dotDirectoryFile));
109 KFileMetaData::UserMetaData metadata(localFolder);
110 const QString viewProperties = metadata.attribute(QStringLiteral("kde.fm.viewproperties#1"));
111 QVERIFY(viewProperties.isEmpty());
112
113 props.reset(new ViewProperties(testDirUrl));
114 QVERIFY(props->isAutoSaveEnabled());
115 QCOMPARE(props->sortRole(), "someNewSortRole");
116 props.reset();
117
118 metadata = KFileMetaData::UserMetaData(destinationDir);
119 if (metadata.isSupported()) {
120 QVERIFY(metadata.hasAttribute("kde.fm.viewproperties#1"));
121 } else {
122 QVERIFY(QFile::exists(destinationDir + "/.directory"));
123 }
124
125 // un-restrict write permissions
126 QFile(localFolder).setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner);
127 }
128
129 void ViewPropertiesTest::testAutoSave()
130 {
131 QString dotDirectoryFile = m_testDir->url().toLocalFile() + "/.directory";
132 QVERIFY(!QFile::exists(dotDirectoryFile));
133
134 QScopedPointer<ViewProperties> props(new ViewProperties(m_testDir->url()));
135 QVERIFY(props->isAutoSaveEnabled());
136 props->setSortRole("someNewSortRole");
137 props.reset();
138
139 KFileMetaData::UserMetaData metadata(m_testDir->url().toLocalFile());
140 if (metadata.isSupported()) {
141 auto viewProperties = metadata.attribute(QStringLiteral("kde.fm.viewproperties#1"));
142 QVERIFY(!viewProperties.isEmpty());
143 QVERIFY(!QFile::exists(dotDirectoryFile));
144 } else {
145 QVERIFY(QFile::exists(dotDirectoryFile));
146 }
147 }
148
149 void ViewPropertiesTest::testParamMigrationToFileAttr()
150 {
151 QString dotDirectoryFilePath = m_testDir->url().toLocalFile() + "/.directory";
152 QVERIFY(!QFile::exists(dotDirectoryFilePath));
153
154 const char *settingsContent = R"SETTINGS("
155 [Dolphin]
156 Version=4
157 ViewMode=1
158 Timestamp=2023,12,29,10,44,15.793
159 VisibleRoles=text,CustomizedDetails,Details_text,Details_modificationtime,Details_type
160
161 [Settings]
162 HiddenFilesShown=true)SETTINGS";
163 auto dotDirectoryFile = QFile(dotDirectoryFilePath);
164 QVERIFY(dotDirectoryFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate));
165 QTextStream out(&dotDirectoryFile);
166 out << settingsContent;
167 dotDirectoryFile.close();
168
169 KFileMetaData::UserMetaData metadata(m_testDir->url().toLocalFile());
170 {
171 QScopedPointer<ViewProperties> props(new ViewProperties(m_testDir->url()));
172 QCOMPARE(props->viewMode(), DolphinView::Mode::DetailsView);
173 QVERIFY(props->hiddenFilesShown());
174 props->save();
175
176 if (metadata.isSupported()) {
177 auto viewProperties = metadata.attribute(QStringLiteral("kde.fm.viewproperties#1"));
178 QVERIFY(!viewProperties.isEmpty());
179 QVERIFY(!QFile::exists(dotDirectoryFilePath));
180 } else {
181 QVERIFY(QFile::exists(dotDirectoryFilePath));
182 }
183 }
184
185 ViewProperties props(m_testDir->url());
186 QCOMPARE(props.viewMode(), DolphinView::Mode::DetailsView);
187 QVERIFY(props.hiddenFilesShown());
188 }
189
190 void ViewPropertiesTest::testParamMigrationToFileAttrKeepDirectory()
191 {
192 QString dotDirectoryFilePath = m_testDir->url().toLocalFile() + "/.directory";
193 QVERIFY(!QFile::exists(dotDirectoryFilePath));
194
195 const char *settingsContent = R"SETTINGS("
196 [Dolphin]
197 Version=4
198 ViewMode=1
199 Timestamp=2023,12,29,10,44,15.793
200 VisibleRoles=text,CustomizedDetails,Details_text,Details_modificationtime,Details_type
201
202 [Settings]
203 HiddenFilesShown=true
204
205 [Other]
206 ThoseShouldBeKept=true
207 )SETTINGS";
208 auto dotDirectoryFile = QFile(dotDirectoryFilePath);
209 QVERIFY(dotDirectoryFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate));
210 QTextStream out(&dotDirectoryFile);
211 out << settingsContent;
212 dotDirectoryFile.close();
213
214 KFileMetaData::UserMetaData metadata(m_testDir->url().toLocalFile());
215 {
216 QScopedPointer<ViewProperties> props(new ViewProperties(m_testDir->url()));
217 QCOMPARE(props->viewMode(), DolphinView::Mode::DetailsView);
218 QVERIFY(props->hiddenFilesShown());
219 props->save();
220
221 if (metadata.isSupported()) {
222 auto viewProperties = metadata.attribute(QStringLiteral("kde.fm.viewproperties#1"));
223 QVERIFY(!viewProperties.isEmpty());
224 }
225
226 QVERIFY(QFile::exists(dotDirectoryFilePath));
227 KConfig directorySettings(dotDirectoryFilePath, KConfig::SimpleConfig);
228 QCOMPARE(directorySettings.groupList(), {"Other"});
229 }
230
231 ViewProperties props(m_testDir->url());
232 QVERIFY(props.hiddenFilesShown());
233 QCOMPARE(props.viewMode(), DolphinView::Mode::DetailsView);
234
235 QVERIFY(QFile::exists(dotDirectoryFilePath));
236 }
237
238 void ViewPropertiesTest::testExtendedAttributeFull()
239 {
240 #ifndef Q_OS_UNIX
241 QSKIP("Only unix is supported, for this test");
242 #endif
243 QString dotDirectoryFile = m_testDir->url().toLocalFile() + "/.directory";
244 QVERIFY(!QFile::exists(dotDirectoryFile));
245
246 KFileMetaData::UserMetaData metadata(m_testDir->url().toLocalFile());
247 if (!metadata.isSupported()) {
248 QSKIP("need extended attribute/filesystem metadata to be usefull");
249 }
250
251 QStorageInfo storageInfo(m_testDir->url().toLocalFile());
252 auto blockSize = storageInfo.blockSize();
253
254 KFileMetaData::UserMetaData::Error result;
255 // write a close to block size theorical maximum size for attributes in Linux for ext4
256 // and btrfs (4Kib typically) when ReiserFS/XFS allow XATTR_SIZE_MAX (64Kib)
257 result = metadata.setAttribute("data", QString(blockSize - 50, 'a'));
258 if (result != KFileMetaData::UserMetaData::NoSpace) {
259 QSKIP("File system supports metadata bigger than file system block size");
260 }
261
262 // write a close to 4k attribute, maximum size in Linux for ext4
263 // so next writing the file metadata fails
264 result = metadata.setAttribute("data", QString(blockSize - 60, 'a'));
265 QCOMPARE(result, KFileMetaData::UserMetaData::NoError);
266
267 QScopedPointer<ViewProperties> props(new ViewProperties(m_testDir->url()));
268 QVERIFY(props->isAutoSaveEnabled());
269 props->setSortRole("someNewSortRole");
270 props.reset();
271
272 if (metadata.isSupported()) {
273 auto viewProperties = metadata.attribute(QStringLiteral("kde.fm.viewproperties#1"));
274 QVERIFY(viewProperties.isEmpty());
275 QVERIFY(QFile::exists(dotDirectoryFile));
276
277 QFile dotDirectory(dotDirectoryFile);
278 KConfig viewSettings(dotDirectoryFile, KConfig::SimpleConfig);
279 QCOMPARE(viewSettings.groupList(), {"Dolphin"});
280 QCOMPARE(viewSettings.group("Dolphin").readEntry("SortRole"), "someNewSortRole");
281 } else {
282 QVERIFY(QFile::exists(dotDirectoryFile));
283 }
284 }
285
286 void ViewPropertiesTest::testUseAsDefaultViewSettings()
287 {
288 // Create a global viewproperties folder
289 QUrl globalPropertiesPath =
290 QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation).append("/view_properties/").append(QStringLiteral("global")));
291 QVERIFY(QDir().mkpath(globalPropertiesPath.toLocalFile()));
292 auto cleanupGlobalDir = qScopeGuard([globalPropertiesPath] {
293 QDir().rmdir(globalPropertiesPath.toLocalFile());
294 });
295 ViewProperties globalProps(globalPropertiesPath);
296
297 // Check that theres no .directory file and metadata is supported
298 QString dotDirectoryFile = m_testDir->url().toLocalFile() + "/.directory";
299 QVERIFY(!QFile::exists(dotDirectoryFile));
300 KFileMetaData::UserMetaData testDirMetadata(m_testDir->url().toLocalFile());
301 KFileMetaData::UserMetaData globalDirMetadata(globalPropertiesPath.toLocalFile());
302 if (!testDirMetadata.isSupported()) {
303 QSKIP("need extended attribute/filesystem metadata to be usefull");
304 }
305
306 const auto newDefaultViewMode = DolphinView::Mode::DetailsView;
307
308 // Equivalent of useAsDefault in ViewPropertiesDialog
309 // This sets the DetailsView as default viewMode
310 GeneralSettings::setGlobalViewProps(true);
311 globalProps.setViewMode(newDefaultViewMode);
312 globalProps.setDirProperties(globalProps);
313 globalProps.save();
314 GeneralSettings::setGlobalViewProps(false);
315
316 // Load default data
317 QScopedPointer<ViewProperties> globalDirProperties(new ViewProperties(globalPropertiesPath));
318 auto defaultData = globalDirProperties.data();
319
320 // Load testdir data
321 QScopedPointer<ViewProperties> testDirProperties(new ViewProperties(m_testDir->url()));
322 auto testData = testDirProperties.data();
323
324 // Make sure globalDirProperties are not empty, so they will be used
325 auto globalDirPropString = globalDirMetadata.attribute(QStringLiteral("kde.fm.viewproperties#1"));
326 QVERIFY(!globalDirPropString.isEmpty());
327
328 // Make sure testDirProperties is empty, so default values are used for it
329 auto testDirPropString = testDirMetadata.attribute(QStringLiteral("kde.fm.viewproperties#1"));
330 QVERIFY(testDirPropString.isEmpty());
331
332 // Compare that default and new folder viewMode is the new default
333 QCOMPARE(defaultData->viewMode(), newDefaultViewMode);
334 QCOMPARE(testData->viewMode(), defaultData->viewMode());
335 }
336
337 void ViewPropertiesTest::testUseAsCustomDefaultViewSettings()
338 {
339 // Create a global viewproperties folder
340 QUrl globalPropertiesPath =
341 QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation).append("/view_properties/").append(QStringLiteral("global")));
342 QVERIFY(QDir().mkpath(globalPropertiesPath.toLocalFile()));
343 auto cleanupGlobalDir = qScopeGuard([globalPropertiesPath] {
344 QDir().rmdir(globalPropertiesPath.toLocalFile());
345 });
346 ViewProperties globalProps(globalPropertiesPath);
347
348 // Check that theres no .directory file and metadata is supported
349 QString dotDirectoryFile = m_testDir->url().toLocalFile() + "/.directory";
350 QVERIFY(!QFile::exists(dotDirectoryFile));
351 KFileMetaData::UserMetaData testDirMetadata(m_testDir->url().toLocalFile());
352 KFileMetaData::UserMetaData globalDirMetadata(globalPropertiesPath.toLocalFile());
353 if (!testDirMetadata.isSupported()) {
354 QSKIP("need extended attribute/filesystem metadata to be usefull");
355 }
356
357 // Equivalent of useAsDefault in ViewPropertiesDialog
358 // This sets the DetailsView as default viewMode
359 GeneralSettings::setGlobalViewProps(true);
360 globalProps.setViewMode(DolphinView::Mode::DetailsView);
361 globalProps.setDirProperties(globalProps);
362 globalProps.save();
363 GeneralSettings::setGlobalViewProps(false);
364
365 // Make sure globalDirProperties are not empty, so they will be used
366 auto globalDirPropString = globalDirMetadata.attribute(QStringLiteral("kde.fm.viewproperties#1"));
367 QVERIFY(!globalDirPropString.isEmpty());
368
369 // Load default data
370 QScopedPointer<ViewProperties> globalDirProperties(new ViewProperties(globalPropertiesPath));
371 auto defaultData = globalDirProperties.data();
372 QCOMPARE(defaultData->viewMode(), DolphinView::Mode::DetailsView);
373
374 // Load testdir data, set to icon, i.e default hardcoded, not current user default
375 QScopedPointer<ViewProperties> testDirProperties(new ViewProperties(m_testDir->url()));
376 testDirProperties->setViewMode(DolphinView::Mode::IconsView);
377 testDirProperties->save();
378
379 // testDirProperties is not default
380 auto testDirPropString = testDirMetadata.attribute(QStringLiteral("kde.fm.viewproperties#1"));
381 QVERIFY(!testDirPropString.isEmpty());
382 QCOMPARE(testDirProperties.data()->viewMode(), DolphinView::Mode::IconsView);
383
384 // testDirProperties is now default
385 testDirProperties->setViewMode(DolphinView::Mode::DetailsView);
386 testDirProperties->save();
387
388 // no more metedata => the defaults settings are in effect for the folder
389 testDirPropString = testDirMetadata.attribute(QStringLiteral("kde.fm.viewproperties#1"));
390 QVERIFY(testDirPropString.isEmpty());
391 QCOMPARE(testDirProperties.data()->viewMode(), DolphinView::Mode::DetailsView);
392 }
393
394 QTEST_GUILESS_MAIN(ViewPropertiesTest)
395
396 #include "viewpropertiestest.moc"