]> cloud.milkyroute.net Git - dolphin.git/blob - src/tests/viewpropertiestest.cpp
f23ad4fc859872e8d58ff8dbc9424fa177dd6972
[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 new test directory for this test to make sure the settings are defaults
289 auto testDir = new TestDir(QDir::homePath() + "/.viewPropertiesTest-");
290 auto cleanupTestDir = qScopeGuard([testDir] {
291 delete testDir;
292 });
293
294 // Create a global viewproperties folder
295 QUrl globalPropertiesPath =
296 QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation).append("/view_properties/").append(QStringLiteral("global")));
297 QVERIFY(QDir().mkpath(globalPropertiesPath.toLocalFile()));
298 auto cleanupGlobalDir = qScopeGuard([globalPropertiesPath] {
299 QDir().rmdir(globalPropertiesPath.toLocalFile());
300 });
301 ViewProperties globalProps(globalPropertiesPath);
302
303 // Check that theres no .directory file and metadata is supported
304 QString dotDirectoryFile = testDir->url().toLocalFile() + "/.directory";
305 QVERIFY(!QFile::exists(dotDirectoryFile));
306 KFileMetaData::UserMetaData testDirMetadata(testDir->url().toLocalFile());
307 KFileMetaData::UserMetaData globalDirMetadata(globalPropertiesPath.toLocalFile());
308 if (!testDirMetadata.isSupported()) {
309 QSKIP("need extended attribute/filesystem metadata to be usefull");
310 }
311
312 const auto newDefaultViewMode = DolphinView::Mode::DetailsView;
313
314 // Equivalent of useAsDefault in ViewPropertiesDialog
315 // This sets the DetailsView as default viewMode
316 GeneralSettings::setGlobalViewProps(true);
317 globalProps.setViewMode(newDefaultViewMode);
318 globalProps.setDirProperties(globalProps);
319 globalProps.save();
320 GeneralSettings::setGlobalViewProps(false);
321
322 // Load default data
323 QScopedPointer<ViewProperties> globalDirProperties(new ViewProperties(globalPropertiesPath));
324 auto defaultData = globalDirProperties.data();
325
326 // Load testdir data
327 QScopedPointer<ViewProperties> testDirProperties(new ViewProperties(testDir->url()));
328 auto testData = testDirProperties.data();
329
330 // Make sure globalDirProperties are not empty, so they will be used
331 auto globalDirPropString = globalDirMetadata.attribute(QStringLiteral("kde.fm.viewproperties#1"));
332 QVERIFY(!globalDirPropString.isEmpty());
333
334 // Make sure testDirProperties is empty, so default values are used for it
335 auto testDirPropString = testDirMetadata.attribute(QStringLiteral("kde.fm.viewproperties#1"));
336 QVERIFY(testDirPropString.isEmpty());
337
338 // Compare that default and new folder viewMode is the new default
339 QCOMPARE(defaultData->viewMode(), newDefaultViewMode);
340 QCOMPARE(testData->viewMode(), defaultData->viewMode());
341 }
342
343 void ViewPropertiesTest::testUseAsCustomDefaultViewSettings()
344 {
345 // Create new test directory for this test to make sure the settings are defaults
346 auto testDir = new TestDir(QDir::homePath() + "/.viewPropertiesTest-");
347 auto cleanupTestDir = qScopeGuard([testDir] {
348 delete testDir;
349 });
350
351 // Create a global viewproperties folder
352 QUrl globalPropertiesPath =
353 QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation).append("/view_properties/").append(QStringLiteral("global")));
354 QVERIFY(QDir().mkpath(globalPropertiesPath.toLocalFile()));
355 auto cleanupGlobalDir = qScopeGuard([globalPropertiesPath] {
356 QDir().rmdir(globalPropertiesPath.toLocalFile());
357 });
358 ViewProperties globalProps(globalPropertiesPath);
359
360 // Check that theres no .directory file and metadata is supported
361 QString dotDirectoryFile = testDir->url().toLocalFile() + "/.directory";
362 QVERIFY(!QFile::exists(dotDirectoryFile));
363 KFileMetaData::UserMetaData testDirMetadata(testDir->url().toLocalFile());
364 KFileMetaData::UserMetaData globalDirMetadata(globalPropertiesPath.toLocalFile());
365 if (!testDirMetadata.isSupported()) {
366 QSKIP("need extended attribute/filesystem metadata to be usefull");
367 }
368
369 // Equivalent of useAsDefault in ViewPropertiesDialog
370 // This sets the DetailsView as default viewMode
371 GeneralSettings::setGlobalViewProps(true);
372 globalProps.setViewMode(DolphinView::Mode::DetailsView);
373 globalProps.setDirProperties(globalProps);
374 globalProps.save();
375 GeneralSettings::setGlobalViewProps(false);
376
377 // Make sure globalDirProperties are not empty, so they will be used
378 auto globalDirPropString = globalDirMetadata.attribute(QStringLiteral("kde.fm.viewproperties#1"));
379 QVERIFY(!globalDirPropString.isEmpty());
380
381 // Load default data
382 QScopedPointer<ViewProperties> globalDirProperties(new ViewProperties(globalPropertiesPath));
383 auto defaultData = globalDirProperties.data();
384 QCOMPARE(defaultData->viewMode(), DolphinView::Mode::DetailsView);
385
386 // Load testdir data, set to icon, i.e default hardcoded, not current user default
387 QScopedPointer<ViewProperties> testDirProperties(new ViewProperties(testDir->url()));
388 testDirProperties->setViewMode(DolphinView::Mode::IconsView);
389 testDirProperties->save();
390
391 // testDirProperties is not default
392 auto testDirPropString = testDirMetadata.attribute(QStringLiteral("kde.fm.viewproperties#1"));
393 QVERIFY(!testDirPropString.isEmpty());
394 QCOMPARE(testDirProperties.data()->viewMode(), DolphinView::Mode::IconsView);
395
396 // testDirProperties is now default
397 testDirProperties->setViewMode(DolphinView::Mode::DetailsView);
398 testDirProperties->save();
399
400 // no more metedata => the defaults settings are in effect for the folder
401 testDirPropString = testDirMetadata.attribute(QStringLiteral("kde.fm.viewproperties#1"));
402 QVERIFY(testDirPropString.isEmpty());
403 QCOMPARE(testDirProperties.data()->viewMode(), DolphinView::Mode::DetailsView);
404 }
405
406 QTEST_GUILESS_MAIN(ViewPropertiesTest)
407
408 #include "viewpropertiestest.moc"