@@ -238,6 +238,83 @@ private Q_SLOTS:
238
238
QVERIFY (!fakeFolder.currentRemoteState ().find (QStringLiteral (" C/.foo" )));
239
239
QVERIFY (!fakeFolder.currentRemoteState ().find (QStringLiteral (" C/bar" )));
240
240
}
241
+
242
+ void testNameNormalization_data ()
243
+ {
244
+ QTest::addColumn<QString>(" correct" );
245
+ QTest::addColumn<QString>(" incorrect" );
246
+
247
+ const unsigned char a_umlaut_composed_bytes[] = {0xc3 , 0xa4 , 0x00 };
248
+ const QString a_umlaut_composed = QString::fromUtf8 (reinterpret_cast <const char *>(a_umlaut_composed_bytes));
249
+ const QString a_umlaut_decomposed = a_umlaut_composed.normalized (QString::NormalizationForm_D);
250
+
251
+ QTest::newRow (" a_umlaut decomposed" ) << a_umlaut_decomposed << a_umlaut_composed;
252
+ QTest::newRow (" a_umlaut composed" ) << a_umlaut_composed << a_umlaut_decomposed;
253
+ }
254
+
255
+ // Test that when a file/directory name on the remote is encoded in NFC, the local name is encoded
256
+ // in the same way, and that a subsequent sync does not change anything. And the same for NFD.
257
+ void testNameNormalization ()
258
+ {
259
+ QFETCH_GLOBAL (Vfs::Mode, vfsMode);
260
+ QFETCH_GLOBAL (bool , filesAreDehydrated);
261
+
262
+ QFETCH (QString, correct);
263
+ QFETCH (QString, incorrect);
264
+
265
+ // Create an empty remote folder
266
+ FakeFolder fakeFolder ({FileInfo{}}, vfsMode, filesAreDehydrated);
267
+ OperationCounter counter (fakeFolder);
268
+
269
+ // Create a file with an a-umlout in the "correct" normalization:
270
+ fakeFolder.remoteModifier ().mkdir (QStringLiteral (" P" ));
271
+ fakeFolder.remoteModifier ().mkdir (QStringLiteral (" P/A" ));
272
+ fakeFolder.remoteModifier ().insert (QStringLiteral (" P/A/" ) + correct);
273
+
274
+ // Same for a directory, holding a "normal" file:
275
+ fakeFolder.remoteModifier ().mkdir (QStringLiteral (" P/B" ) + correct);
276
+ fakeFolder.remoteModifier ().insert (QStringLiteral (" P/B" ) + correct + QStringLiteral (" /b" ));
277
+
278
+ LocalDiscoveryTracker tracker;
279
+ connect (&fakeFolder.syncEngine (), &SyncEngine::itemCompleted, &tracker, &LocalDiscoveryTracker::slotItemCompleted);
280
+ connect (&fakeFolder.syncEngine (), &SyncEngine::finished, &tracker, &LocalDiscoveryTracker::slotSyncFinished);
281
+
282
+ // First sync: discover that there are files/directories on the server that are not yet synced to the local end
283
+ QVERIFY (fakeFolder.applyLocalModificationsAndSync ());
284
+
285
+ // Check that locally we have the file and the directory with the correct names:
286
+ {
287
+ auto localState = fakeFolder.currentLocalState ();
288
+ QVERIFY (localState.find (QStringLiteral (" P/A/" ) + correct) != nullptr ); // check if the file exists
289
+ QVERIFY (localState.find (QStringLiteral (" P/B" ) + correct + QStringLiteral (" /b" )) != nullptr ); // check if the file exists
290
+ }
291
+
292
+ counter.reset ();
293
+
294
+ qDebug () << " *** MARK" ; // Log marker to check if a PUT/DELETE shows up in the second sync
295
+
296
+ // Force a full local discovery on the next sync, which forces a walk of the (local) file system, reading back names (and file sizes/mtimes/etc.)...
297
+ fakeFolder.syncEngine ().setLocalDiscoveryOptions (LocalDiscoveryStyle::DatabaseAndFilesystem, {QStringLiteral (" P" )});
298
+ tracker.startSyncFullDiscovery ();
299
+
300
+ // ... and start the second sync:
301
+ QVERIFY (fakeFolder.applyLocalModificationsAndSync ());
302
+
303
+ // If the normalization of the file/directory name did not change, no rename/move/etc. should have been detected, so check that the client didn't issue
304
+ // any of these operations:
305
+ QCOMPARE (counter.nDELETE , 0 );
306
+ QCOMPARE (counter.nMOVE , 0 );
307
+ QCOMPARE (counter.nPUT , 0 );
308
+
309
+ // Check that the remote names are unchanged, and that no "incorrect" names have been introduced:
310
+ FileInfo &remoteState = fakeFolder.currentRemoteState ();
311
+ QVERIFY (remoteState.find (QStringLiteral (" P/A/" ) + correct) != nullptr ); // check if the file still exists in the original normalization
312
+ QVERIFY (remoteState.find (QStringLiteral (" P/A/" ) + incorrect) == nullptr ); // there should NOT be a file with another normalization
313
+ QVERIFY (remoteState.find (QStringLiteral (" P/B" ) + correct + QStringLiteral (" /b" ))
314
+ != nullptr ); // check if the directory still exists in the original normalization
315
+ QVERIFY (remoteState.find (QStringLiteral (" P/B" ) + incorrect + QStringLiteral (" /b" ))
316
+ == nullptr ); // there should NOT be a directory with another normalization
317
+ }
241
318
};
242
319
243
320
QTEST_GUILESS_MAIN (TestLocalDiscovery)
0 commit comments