testsyncfilestatustracker.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /*
  2. * This software is in the public domain, furnished "as is", without technical
  3. * support, and with no warranty, express or implied, as to its usefulness for
  4. * any purpose.
  5. *
  6. */
  7. #include <QtTest>
  8. #include "syncenginetestutils.h"
  9. using namespace OCC;
  10. class StatusPushSpy : public QSignalSpy
  11. {
  12. SyncEngine &_syncEngine;
  13. public:
  14. StatusPushSpy(SyncEngine &syncEngine)
  15. : QSignalSpy(&syncEngine.syncFileStatusTracker(), SIGNAL(fileStatusChanged(const QString&, SyncFileStatus)))
  16. , _syncEngine(syncEngine)
  17. { }
  18. SyncFileStatus statusOf(const QString &relativePath) const {
  19. QFileInfo file(_syncEngine.localPath(), relativePath);
  20. // Start from the end to get the latest status
  21. for (int i = size() - 1; i >= 0; --i) {
  22. if (QFileInfo(at(i)[0].toString()) == file)
  23. return at(i)[1].value<SyncFileStatus>();
  24. }
  25. return SyncFileStatus();
  26. }
  27. };
  28. class TestSyncFileStatusTracker : public QObject
  29. {
  30. Q_OBJECT
  31. void verifyThatPushMatchesPull(const FakeFolder &fakeFolder, const StatusPushSpy &statusSpy) {
  32. QString root = fakeFolder.localPath();
  33. QDirIterator it(root, QDir::AllEntries | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
  34. while (it.hasNext()) {
  35. QString filePath = it.next().mid(root.size());
  36. SyncFileStatus pushedStatus = statusSpy.statusOf(filePath);
  37. if (pushedStatus != SyncFileStatus())
  38. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus(filePath), pushedStatus);
  39. }
  40. }
  41. private slots:
  42. void parentsGetSyncStatusUploadDownload() {
  43. FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
  44. fakeFolder.localModifier().appendByte("B/b1");
  45. fakeFolder.remoteModifier().appendByte("C/c1");
  46. StatusPushSpy statusSpy(fakeFolder.syncEngine());
  47. fakeFolder.scheduleSync();
  48. fakeFolder.execUntilBeforePropagation();
  49. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  50. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  51. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusSync));
  52. QCOMPARE(statusSpy.statusOf("B/b1"), SyncFileStatus(SyncFileStatus::StatusSync));
  53. QCOMPARE(statusSpy.statusOf("C"), SyncFileStatus(SyncFileStatus::StatusSync));
  54. QCOMPARE(statusSpy.statusOf("C/c1"), SyncFileStatus(SyncFileStatus::StatusSync));
  55. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  56. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A/a1"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  57. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("B/b2"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  58. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("C/c2"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  59. statusSpy.clear();
  60. fakeFolder.execUntilFinished();
  61. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  62. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  63. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  64. QCOMPARE(statusSpy.statusOf("B/b1"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  65. QCOMPARE(statusSpy.statusOf("C"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  66. QCOMPARE(statusSpy.statusOf("C/c1"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  67. QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
  68. }
  69. void parentsGetSyncStatusNewFileUploadDownload() {
  70. FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
  71. fakeFolder.localModifier().insert("B/b0");
  72. fakeFolder.remoteModifier().insert("C/c0");
  73. StatusPushSpy statusSpy(fakeFolder.syncEngine());
  74. fakeFolder.scheduleSync();
  75. fakeFolder.execUntilBeforePropagation();
  76. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  77. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  78. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusSync));
  79. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusSync));
  80. QCOMPARE(statusSpy.statusOf("C"), SyncFileStatus(SyncFileStatus::StatusSync));
  81. QCOMPARE(statusSpy.statusOf("C/c0"), SyncFileStatus(SyncFileStatus::StatusSync));
  82. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  83. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A/a1"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  84. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("B/b1"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  85. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("C/c1"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  86. statusSpy.clear();
  87. fakeFolder.execUntilFinished();
  88. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  89. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  90. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  91. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  92. QCOMPARE(statusSpy.statusOf("C"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  93. QCOMPARE(statusSpy.statusOf("C/c0"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  94. QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
  95. }
  96. void parentsGetSyncStatusNewDirDownload() {
  97. FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
  98. fakeFolder.remoteModifier().mkdir("D");
  99. fakeFolder.remoteModifier().insert("D/d0");
  100. StatusPushSpy statusSpy(fakeFolder.syncEngine());
  101. fakeFolder.scheduleSync();
  102. fakeFolder.execUntilBeforePropagation();
  103. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  104. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  105. QCOMPARE(statusSpy.statusOf("D"), SyncFileStatus(SyncFileStatus::StatusSync));
  106. QCOMPARE(statusSpy.statusOf("D/d0"), SyncFileStatus(SyncFileStatus::StatusSync));
  107. fakeFolder.execUntilItemCompleted("D");
  108. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  109. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  110. QCOMPARE(statusSpy.statusOf("D"), SyncFileStatus(SyncFileStatus::StatusSync));
  111. QCOMPARE(statusSpy.statusOf("D/d0"), SyncFileStatus(SyncFileStatus::StatusSync));
  112. fakeFolder.execUntilFinished();
  113. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  114. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  115. QCOMPARE(statusSpy.statusOf("D"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  116. QCOMPARE(statusSpy.statusOf("D/d0"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  117. QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
  118. }
  119. void parentsGetSyncStatusNewDirUpload() {
  120. FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
  121. fakeFolder.localModifier().mkdir("D");
  122. fakeFolder.localModifier().insert("D/d0");
  123. StatusPushSpy statusSpy(fakeFolder.syncEngine());
  124. fakeFolder.scheduleSync();
  125. fakeFolder.execUntilBeforePropagation();
  126. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  127. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  128. QCOMPARE(statusSpy.statusOf("D"), SyncFileStatus(SyncFileStatus::StatusSync));
  129. QCOMPARE(statusSpy.statusOf("D/d0"), SyncFileStatus(SyncFileStatus::StatusSync));
  130. fakeFolder.execUntilItemCompleted("D");
  131. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  132. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  133. QCOMPARE(statusSpy.statusOf("D"), SyncFileStatus(SyncFileStatus::StatusSync));
  134. QCOMPARE(statusSpy.statusOf("D/d0"), SyncFileStatus(SyncFileStatus::StatusSync));
  135. fakeFolder.execUntilFinished();
  136. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  137. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  138. QCOMPARE(statusSpy.statusOf("D"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  139. QCOMPARE(statusSpy.statusOf("D/d0"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  140. QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
  141. }
  142. void parentsGetSyncStatusDeleteUpDown() {
  143. FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
  144. fakeFolder.remoteModifier().remove("B/b1");
  145. fakeFolder.localModifier().remove("C/c1");
  146. StatusPushSpy statusSpy(fakeFolder.syncEngine());
  147. fakeFolder.scheduleSync();
  148. fakeFolder.execUntilBeforePropagation();
  149. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  150. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  151. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusSync));
  152. // Discovered as remotely removed, pending for local removal.
  153. QCOMPARE(statusSpy.statusOf("B/b1"), SyncFileStatus(SyncFileStatus::StatusSync));
  154. QCOMPARE(statusSpy.statusOf("C"), SyncFileStatus(SyncFileStatus::StatusSync));
  155. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  156. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("B/b2"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  157. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("C/c2"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  158. statusSpy.clear();
  159. fakeFolder.execUntilFinished();
  160. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  161. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  162. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  163. QCOMPARE(statusSpy.statusOf("C"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  164. QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
  165. }
  166. void warningStatusForExcludedFile() {
  167. FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
  168. fakeFolder.syncEngine().excludedFiles().addExcludeExpr("A/a1");
  169. fakeFolder.syncEngine().excludedFiles().addExcludeExpr("B");
  170. fakeFolder.localModifier().appendByte("A/a1");
  171. fakeFolder.localModifier().appendByte("B/b1");
  172. StatusPushSpy statusSpy(fakeFolder.syncEngine());
  173. fakeFolder.scheduleSync();
  174. fakeFolder.execUntilBeforePropagation();
  175. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  176. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusWarning));
  177. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusWarning));
  178. QEXPECT_FAIL("", "csync will stop at ignored directories without traversing children, so we don't currently push the status for newly ignored children of an ignored directory.", Continue);
  179. QCOMPARE(statusSpy.statusOf("B/b1"), SyncFileStatus(SyncFileStatus::StatusWarning));
  180. fakeFolder.execUntilFinished();
  181. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  182. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusWarning));
  183. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusWarning));
  184. QEXPECT_FAIL("", "csync will stop at ignored directories without traversing children, so we don't currently push the status for newly ignored children of an ignored directory.", Continue);
  185. QCOMPARE(statusSpy.statusOf("B/b1"), SyncFileStatus(SyncFileStatus::StatusWarning));
  186. QEXPECT_FAIL("", "csync will stop at ignored directories without traversing children, so we don't currently push the status for newly ignored children of an ignored directory.", Continue);
  187. QCOMPARE(statusSpy.statusOf("B/b2"), SyncFileStatus(SyncFileStatus::StatusWarning));
  188. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus(""), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  189. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  190. statusSpy.clear();
  191. // Clears the exclude expr above
  192. fakeFolder.syncEngine().excludedFiles().reloadExcludes();
  193. fakeFolder.scheduleSync();
  194. fakeFolder.execUntilBeforePropagation();
  195. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  196. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusSync));
  197. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusSync));
  198. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusSync));
  199. QCOMPARE(statusSpy.statusOf("B/b1"), SyncFileStatus(SyncFileStatus::StatusSync));
  200. statusSpy.clear();
  201. fakeFolder.execUntilFinished();
  202. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  203. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  204. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  205. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  206. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  207. QCOMPARE(statusSpy.statusOf("B/b1"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  208. QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
  209. }
  210. void parentsGetWarningStatusForError() {
  211. FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
  212. fakeFolder.serverErrorPaths().append("A/a1");
  213. fakeFolder.serverErrorPaths().append("B/b0");
  214. fakeFolder.localModifier().appendByte("A/a1");
  215. fakeFolder.localModifier().insert("B/b0");
  216. StatusPushSpy statusSpy(fakeFolder.syncEngine());
  217. fakeFolder.scheduleSync();
  218. fakeFolder.execUntilBeforePropagation();
  219. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  220. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  221. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusSync));
  222. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusSync));
  223. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusSync));
  224. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusSync));
  225. statusSpy.clear();
  226. fakeFolder.execUntilFinished();
  227. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  228. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusWarning));
  229. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusWarning));
  230. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusError));
  231. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A/a2"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  232. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusWarning));
  233. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusError));
  234. statusSpy.clear();
  235. // Remove the error and start a second sync, the blacklist should kick in
  236. fakeFolder.serverErrorPaths().clear();
  237. fakeFolder.scheduleSync();
  238. fakeFolder.execUntilBeforePropagation();
  239. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  240. // A/a1 and B/b0 should be on the black list for the next few seconds
  241. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusWarning));
  242. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusWarning));
  243. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusError));
  244. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusWarning));
  245. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusError));
  246. statusSpy.clear();
  247. fakeFolder.execUntilFinished();
  248. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  249. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusWarning));
  250. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusWarning));
  251. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusError));
  252. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A/a2"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  253. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusWarning));
  254. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusError));
  255. statusSpy.clear();
  256. // Start a third sync, this time together with a real file to sync
  257. fakeFolder.localModifier().appendByte("C/c1");
  258. fakeFolder.scheduleSync();
  259. fakeFolder.execUntilBeforePropagation();
  260. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  261. // The root should show SYNC even though there is an error underneath,
  262. // since C/c1 is syncing and the SYNC status has priority.
  263. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  264. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusWarning));
  265. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusError));
  266. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusWarning));
  267. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusError));
  268. QCOMPARE(statusSpy.statusOf("C"), SyncFileStatus(SyncFileStatus::StatusSync));
  269. QCOMPARE(statusSpy.statusOf("C/c1"), SyncFileStatus(SyncFileStatus::StatusSync));
  270. statusSpy.clear();
  271. fakeFolder.execUntilFinished();
  272. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  273. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusWarning));
  274. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusWarning));
  275. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusError));
  276. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A/a2"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  277. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusWarning));
  278. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusError));
  279. QCOMPARE(statusSpy.statusOf("C"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  280. QCOMPARE(statusSpy.statusOf("C/c1"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  281. statusSpy.clear();
  282. // Another sync after clearing the blacklist entry, everything should return to order.
  283. fakeFolder.syncEngine().journal()->wipeErrorBlacklistEntry("A/a1");
  284. fakeFolder.syncEngine().journal()->wipeErrorBlacklistEntry("B/b0");
  285. fakeFolder.scheduleSync();
  286. fakeFolder.execUntilBeforePropagation();
  287. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  288. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  289. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusSync));
  290. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusSync));
  291. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusSync));
  292. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusSync));
  293. statusSpy.clear();
  294. fakeFolder.execUntilFinished();
  295. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  296. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  297. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  298. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  299. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  300. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  301. QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
  302. }
  303. void parentsGetWarningStatusForError_SibblingStartsWithPath() {
  304. // A is a parent of A/a1, but A/a is not even if it's a substring of A/a1
  305. FakeFolder fakeFolder{{QString{},{
  306. {QStringLiteral("A"), {
  307. {QStringLiteral("a"), 4},
  308. {QStringLiteral("a1"), 4}
  309. }}}}};
  310. fakeFolder.serverErrorPaths().append("A/a1");
  311. fakeFolder.localModifier().appendByte("A/a1");
  312. fakeFolder.scheduleSync();
  313. fakeFolder.execUntilBeforePropagation();
  314. // The SyncFileStatusTraker won't push any status for all of them, test with a pull.
  315. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus(""), SyncFileStatus(SyncFileStatus::StatusSync));
  316. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A"), SyncFileStatus(SyncFileStatus::StatusSync));
  317. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A/a1"), SyncFileStatus(SyncFileStatus::StatusSync));
  318. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A/a"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  319. fakeFolder.execUntilFinished();
  320. // We use string matching for paths in the implementation,
  321. // an error should affect only parents and not every path that starts with the problem path.
  322. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus(""), SyncFileStatus(SyncFileStatus::StatusWarning));
  323. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A"), SyncFileStatus(SyncFileStatus::StatusWarning));
  324. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A/a1"), SyncFileStatus(SyncFileStatus::StatusError));
  325. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A/a"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  326. }
  327. void sharedStatus() {
  328. SyncFileStatus sharedUpToDateStatus(SyncFileStatus::StatusUpToDate);
  329. sharedUpToDateStatus.setSharedWithMe(true);
  330. FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
  331. fakeFolder.remoteModifier().insert("S/s0");
  332. fakeFolder.remoteModifier().appendByte("S/s1");
  333. fakeFolder.remoteModifier().insert("B/b3");
  334. fakeFolder.remoteModifier().find("B/b3")->extraDavProperties
  335. = "<oc:share-types><oc:share-type>0</oc:share-type></oc:share-types>";
  336. StatusPushSpy statusSpy(fakeFolder.syncEngine());
  337. fakeFolder.scheduleSync();
  338. fakeFolder.execUntilBeforePropagation();
  339. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  340. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  341. // We don't care about the shared flag for the sync status,
  342. // Mac and Windows won't show it and we can't know it for new files.
  343. QCOMPARE(statusSpy.statusOf("S").tag(), SyncFileStatus::StatusSync);
  344. QCOMPARE(statusSpy.statusOf("S/s0").tag(), SyncFileStatus::StatusSync);
  345. QCOMPARE(statusSpy.statusOf("S/s1").tag(), SyncFileStatus::StatusSync);
  346. fakeFolder.execUntilFinished();
  347. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  348. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  349. QCOMPARE(statusSpy.statusOf("S"), sharedUpToDateStatus);
  350. QEXPECT_FAIL("", "We currently only know if a new file is shared on the second sync, after a PROPFIND.", Continue);
  351. QCOMPARE(statusSpy.statusOf("S/s0"), sharedUpToDateStatus);
  352. QCOMPARE(statusSpy.statusOf("S/s1"), sharedUpToDateStatus);
  353. QCOMPARE(statusSpy.statusOf("B/b1").sharedWithMe(), false);
  354. QCOMPARE(statusSpy.statusOf("B/b3"), sharedUpToDateStatus);
  355. QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
  356. }
  357. };
  358. QTEST_GUILESS_MAIN(TestSyncFileStatusTracker)
  359. #include "testsyncfilestatustracker.moc"