testsyncfilestatustracker.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  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. QEXPECT_FAIL("", "The mkdir completion shouldn't mark it as OK as long as its children aren't done syncing (https://github.com/owncloud/client/issues/4797).", Continue);
  111. QCOMPARE(statusSpy.statusOf("D"), SyncFileStatus(SyncFileStatus::StatusSync));
  112. QCOMPARE(statusSpy.statusOf("D/d0"), SyncFileStatus(SyncFileStatus::StatusSync));
  113. fakeFolder.execUntilFinished();
  114. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  115. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  116. QCOMPARE(statusSpy.statusOf("D"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  117. QCOMPARE(statusSpy.statusOf("D/d0"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  118. QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
  119. }
  120. void parentsGetSyncStatusNewDirUpload() {
  121. FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
  122. fakeFolder.localModifier().mkdir("D");
  123. fakeFolder.localModifier().insert("D/d0");
  124. StatusPushSpy statusSpy(fakeFolder.syncEngine());
  125. fakeFolder.scheduleSync();
  126. fakeFolder.execUntilBeforePropagation();
  127. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  128. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  129. QCOMPARE(statusSpy.statusOf("D"), SyncFileStatus(SyncFileStatus::StatusSync));
  130. QCOMPARE(statusSpy.statusOf("D/d0"), SyncFileStatus(SyncFileStatus::StatusSync));
  131. fakeFolder.execUntilItemCompleted("D");
  132. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  133. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  134. QEXPECT_FAIL("", "The mkdir completion shouldn't mark it as OK as long as its children aren't done syncing (https://github.com/owncloud/client/issues/4797).", Continue);
  135. QCOMPARE(statusSpy.statusOf("D"), SyncFileStatus(SyncFileStatus::StatusSync));
  136. QCOMPARE(statusSpy.statusOf("D/d0"), SyncFileStatus(SyncFileStatus::StatusSync));
  137. fakeFolder.execUntilFinished();
  138. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  139. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  140. QCOMPARE(statusSpy.statusOf("D"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  141. QCOMPARE(statusSpy.statusOf("D/d0"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  142. QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
  143. }
  144. void parentsGetSyncStatusDeleteUpDown() {
  145. FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
  146. fakeFolder.remoteModifier().remove("B/b1");
  147. fakeFolder.localModifier().remove("C/c1");
  148. StatusPushSpy statusSpy(fakeFolder.syncEngine());
  149. fakeFolder.scheduleSync();
  150. fakeFolder.execUntilBeforePropagation();
  151. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  152. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  153. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusSync));
  154. // Discovered as remotely removed, pending for local removal.
  155. QCOMPARE(statusSpy.statusOf("B/b1"), SyncFileStatus(SyncFileStatus::StatusSync));
  156. QEXPECT_FAIL("", "C/c1 was removed locally and the parent should ideally reflect this until it's deleted on the server.", Continue);
  157. QCOMPARE(statusSpy.statusOf("C"), SyncFileStatus(SyncFileStatus::StatusSync));
  158. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  159. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("B/b2"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  160. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("C/c2"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  161. statusSpy.clear();
  162. fakeFolder.execUntilFinished();
  163. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  164. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  165. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  166. QEXPECT_FAIL("", "Probably same cause as the missing SyncFileStatus::StatusSync for C above.", Continue);
  167. QCOMPARE(statusSpy.statusOf("C"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  168. QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
  169. }
  170. void warningStatusForExcludedFile() {
  171. FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
  172. fakeFolder.syncEngine().excludedFiles().addExcludeExpr("A/a1");
  173. fakeFolder.syncEngine().excludedFiles().addExcludeExpr("B");
  174. fakeFolder.localModifier().appendByte("A/a1");
  175. fakeFolder.localModifier().appendByte("B/b1");
  176. StatusPushSpy statusSpy(fakeFolder.syncEngine());
  177. fakeFolder.scheduleSync();
  178. fakeFolder.execUntilBeforePropagation();
  179. // FIXME: Uncomment, fails since A/a1 gets pushed an OK for some reason, but pulls an IGNORE
  180. // verifyThatPushMatchesPull(fakeFolder, statusSpy);
  181. QEXPECT_FAIL("", "We should have received a warning status but didn't yet.", Continue);
  182. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusWarning));
  183. QEXPECT_FAIL("", "We should have received a warning status but didn't yet.", Continue);
  184. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusWarning));
  185. 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);
  186. QCOMPARE(statusSpy.statusOf("B/b1"), SyncFileStatus(SyncFileStatus::StatusWarning));
  187. fakeFolder.execUntilFinished();
  188. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  189. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusWarning));
  190. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusWarning));
  191. 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);
  192. QCOMPARE(statusSpy.statusOf("B/b1"), SyncFileStatus(SyncFileStatus::StatusWarning));
  193. 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);
  194. QCOMPARE(statusSpy.statusOf("B/b2"), SyncFileStatus(SyncFileStatus::StatusWarning));
  195. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus(""), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  196. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  197. statusSpy.clear();
  198. // Clears the exclude expr above
  199. fakeFolder.syncEngine().excludedFiles().reloadExcludes();
  200. fakeFolder.scheduleSync();
  201. fakeFolder.execUntilBeforePropagation();
  202. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  203. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusSync));
  204. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusSync));
  205. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusSync));
  206. QCOMPARE(statusSpy.statusOf("B/b1"), SyncFileStatus(SyncFileStatus::StatusSync));
  207. statusSpy.clear();
  208. fakeFolder.execUntilFinished();
  209. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  210. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  211. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  212. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  213. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  214. QCOMPARE(statusSpy.statusOf("B/b1"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  215. QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
  216. }
  217. void parentsGetWarningStatusForError() {
  218. FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
  219. fakeFolder.serverErrorPaths().append("A/a1");
  220. fakeFolder.serverErrorPaths().append("B/b0");
  221. fakeFolder.localModifier().appendByte("A/a1");
  222. fakeFolder.localModifier().insert("B/b0");
  223. StatusPushSpy statusSpy(fakeFolder.syncEngine());
  224. fakeFolder.scheduleSync();
  225. fakeFolder.execUntilBeforePropagation();
  226. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  227. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  228. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusSync));
  229. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusSync));
  230. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusSync));
  231. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusSync));
  232. statusSpy.clear();
  233. fakeFolder.execUntilFinished();
  234. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  235. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusWarning));
  236. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusWarning));
  237. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusError));
  238. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A/a2"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  239. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusWarning));
  240. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusError));
  241. statusSpy.clear();
  242. // Remove the error and start a second sync, the blacklist should kick in
  243. fakeFolder.serverErrorPaths().clear();
  244. fakeFolder.scheduleSync();
  245. fakeFolder.execUntilBeforePropagation();
  246. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  247. // A/a1 and B/b0 should be on the black list for the next few seconds
  248. QEXPECT_FAIL("", "Only one blacklist item, we shouldn't be showing SYNC.", Continue);
  249. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusWarning));
  250. QEXPECT_FAIL("", "Only one blacklist item, we shouldn't be showing SYNC.", Continue);
  251. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusWarning));
  252. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusError));
  253. QEXPECT_FAIL("", "Only one blacklist item, we shouldn't be showing SYNC.", Continue);
  254. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusWarning));
  255. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusError));
  256. statusSpy.clear();
  257. fakeFolder.execUntilFinished();
  258. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  259. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusWarning));
  260. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusWarning));
  261. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusError));
  262. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A/a2"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  263. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusWarning));
  264. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusError));
  265. statusSpy.clear();
  266. // Start a third sync, this time together with a real file to sync
  267. fakeFolder.localModifier().appendByte("C/c1");
  268. fakeFolder.scheduleSync();
  269. fakeFolder.execUntilBeforePropagation();
  270. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  271. // The root should show SYNC even though there is an error underneath,
  272. // since C/c1 is syncing and the SYNC status has priority.
  273. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  274. QEXPECT_FAIL("", "Only one blacklist item underneath, we shouldn't be showing SYNC.", Continue);
  275. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusWarning));
  276. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusError));
  277. QEXPECT_FAIL("", "Only one blacklist item underneath, we shouldn't be showing SYNC.", Continue);
  278. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusWarning));
  279. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusError));
  280. QCOMPARE(statusSpy.statusOf("C"), SyncFileStatus(SyncFileStatus::StatusSync));
  281. QCOMPARE(statusSpy.statusOf("C/c1"), SyncFileStatus(SyncFileStatus::StatusSync));
  282. statusSpy.clear();
  283. fakeFolder.execUntilFinished();
  284. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  285. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusWarning));
  286. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusWarning));
  287. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusError));
  288. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A/a2"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  289. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusWarning));
  290. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusError));
  291. QCOMPARE(statusSpy.statusOf("C"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  292. QCOMPARE(statusSpy.statusOf("C/c1"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  293. statusSpy.clear();
  294. // Another sync after clearing the blacklist entry, everything should return to order.
  295. fakeFolder.syncEngine().journal()->wipeErrorBlacklistEntry("A/a1");
  296. fakeFolder.syncEngine().journal()->wipeErrorBlacklistEntry("B/b0");
  297. fakeFolder.scheduleSync();
  298. fakeFolder.execUntilBeforePropagation();
  299. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  300. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  301. QEXPECT_FAIL("", "Weird, should be SYNC", Continue);
  302. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusSync));
  303. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusSync));
  304. QEXPECT_FAIL("", "Weird, should be SYNC", Continue);
  305. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusSync));
  306. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusSync));
  307. statusSpy.clear();
  308. fakeFolder.execUntilFinished();
  309. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  310. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  311. QEXPECT_FAIL("", "Probably since it didn't get SYNC above.", Continue);
  312. QCOMPARE(statusSpy.statusOf("A"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  313. QCOMPARE(statusSpy.statusOf("A/a1"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  314. QEXPECT_FAIL("", "Probably since it didn't get SYNC above.", Continue);
  315. QCOMPARE(statusSpy.statusOf("B"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  316. QCOMPARE(statusSpy.statusOf("B/b0"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  317. QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
  318. }
  319. void parentsGetWarningStatusForError_SibblingStartsWithPath() {
  320. // A is a parent of A/a1, but A/a is not even if it's a substring of A/a1
  321. FakeFolder fakeFolder{{QString{},{
  322. {QStringLiteral("A"), {
  323. {QStringLiteral("a"), 4},
  324. {QStringLiteral("a1"), 4}
  325. }}}}};
  326. fakeFolder.serverErrorPaths().append("A/a1");
  327. fakeFolder.localModifier().appendByte("A/a1");
  328. fakeFolder.scheduleSync();
  329. fakeFolder.execUntilBeforePropagation();
  330. // The SyncFileStatusTraker won't push any status for all of them, test with a pull.
  331. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus(""), SyncFileStatus(SyncFileStatus::StatusSync));
  332. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A"), SyncFileStatus(SyncFileStatus::StatusSync));
  333. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A/a1"), SyncFileStatus(SyncFileStatus::StatusSync));
  334. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A/a"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  335. fakeFolder.execUntilFinished();
  336. // We use string matching for paths in the implementation,
  337. // an error should affect only parents and not every path that starts with the problem path.
  338. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus(""), SyncFileStatus(SyncFileStatus::StatusWarning));
  339. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A"), SyncFileStatus(SyncFileStatus::StatusWarning));
  340. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A/a1"), SyncFileStatus(SyncFileStatus::StatusError));
  341. QCOMPARE(fakeFolder.syncEngine().syncFileStatusTracker().fileStatus("A/a"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  342. }
  343. void sharedStatus() {
  344. SyncFileStatus sharedUpToDateStatus(SyncFileStatus::StatusUpToDate);
  345. sharedUpToDateStatus.setSharedWithMe(true);
  346. FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
  347. fakeFolder.remoteModifier().insert("S/s0");
  348. fakeFolder.remoteModifier().appendByte("S/s1");
  349. StatusPushSpy statusSpy(fakeFolder.syncEngine());
  350. fakeFolder.scheduleSync();
  351. fakeFolder.execUntilBeforePropagation();
  352. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  353. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusSync));
  354. // We don't care about the shared flag for the sync status,
  355. // Mac and Windows won't show it and we can't know it for new files.
  356. QCOMPARE(statusSpy.statusOf("S").tag(), SyncFileStatus::StatusSync);
  357. QCOMPARE(statusSpy.statusOf("S/s0").tag(), SyncFileStatus::StatusSync);
  358. QCOMPARE(statusSpy.statusOf("S/s1").tag(), SyncFileStatus::StatusSync);
  359. fakeFolder.execUntilFinished();
  360. verifyThatPushMatchesPull(fakeFolder, statusSpy);
  361. QCOMPARE(statusSpy.statusOf(""), SyncFileStatus(SyncFileStatus::StatusUpToDate));
  362. QCOMPARE(statusSpy.statusOf("S"), sharedUpToDateStatus);
  363. QEXPECT_FAIL("", "We currently only know if a new file is shared on the second sync, after a PROPFIND.", Continue);
  364. QCOMPARE(statusSpy.statusOf("S/s0"), sharedUpToDateStatus);
  365. QCOMPARE(statusSpy.statusOf("S/s1"), sharedUpToDateStatus);
  366. QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
  367. }
  368. };
  369. QTEST_GUILESS_MAIN(TestSyncFileStatusTracker)
  370. #include "testsyncfilestatustracker.moc"