Skip to content

Commit 6a96d3a

Browse files
committed
test(quota): add tests for quota-blocked file protection on parent deletion
Two cases: - quota blocked file survives when its remote parent folder is deleted; already synced siblings are still removed. - regression: a plain new file with no quota error in a server deleted folder continues to be deleted as before. Signed-off-by: Camila Ayres <hello@camilasan.com>
1 parent 3ab307b commit 6a96d3a

1 file changed

Lines changed: 74 additions & 0 deletions

File tree

test/testsyncdelete.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,80 @@ private slots:
5252
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
5353
}
5454

55+
// Verify that a file blocked from uploading by a remote storage quota error is
56+
// protected from local deletion when the remote parent folder is subsequently deleted.
57+
void testQuotaBlockedFileProtectedFromParentFolderDeletion()
58+
{
59+
FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
60+
61+
// Establish an initial clean sync: a1 and a2 exist on both sides.
62+
QVERIFY(fakeFolder.syncOnce());
63+
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
64+
65+
// Add a new local file that will fail to upload due to remote quota (HTTP 507).
66+
fakeFolder.localModifier().insert(QStringLiteral("A/quota_blocked.txt"), 100);
67+
fakeFolder.serverErrorPaths().append(QStringLiteral("A/quota_blocked.txt"), 507);
68+
69+
// Sync: upload fails → file is blacklisted as InsufficientRemoteStorage.
70+
QVERIFY(!fakeFolder.syncOnce());
71+
{
72+
auto entry = fakeFolder.syncJournal().errorBlacklistEntry(QStringLiteral("A/quota_blocked.txt"));
73+
QVERIFY(entry.isValid());
74+
QCOMPARE(entry._errorCategory, SyncJournalErrorBlacklistRecord::InsufficientRemoteStorage);
75+
}
76+
77+
// The file was never uploaded.
78+
QVERIFY(!fakeFolder.currentRemoteState().find(QStringLiteral("A/quota_blocked.txt")));
79+
80+
// Remove the server error so further requests to that path don't return 507.
81+
fakeFolder.serverErrorPaths().clear();
82+
83+
// Server-side: folder A is moved/deleted (e.g., via the web interface).
84+
fakeFolder.remoteModifier().remove(QStringLiteral("A"));
85+
86+
ItemCompletedSpy completeSpy(fakeFolder);
87+
fakeFolder.syncOnce();
88+
89+
// *** Core assertion: quota-blocked file must NOT have been deleted locally. ***
90+
QVERIFY(fakeFolder.currentLocalState().find(QStringLiteral("A/quota_blocked.txt")));
91+
92+
// Parent folder A must also survive because it still contains the protected file.
93+
QVERIFY(fakeFolder.currentLocalState().find(QStringLiteral("A")));
94+
95+
// Previously-synced siblings must have been deleted locally (trust the server).
96+
QVERIFY(!fakeFolder.currentLocalState().find(QStringLiteral("A/a1")));
97+
QVERIFY(!fakeFolder.currentLocalState().find(QStringLiteral("A/a2")));
98+
99+
// The quota-blocked file must still not exist on the server.
100+
QVERIFY(!fakeFolder.currentRemoteState().find(QStringLiteral("A/quota_blocked.txt")));
101+
102+
// The protected file must be reported as an error (or blacklisted-error) item, not silently ignored.
103+
{
104+
auto item = completeSpy.findItem(QStringLiteral("A/quota_blocked.txt"));
105+
QVERIFY(item);
106+
const bool isErrorItem = item->_instruction == CSYNC_INSTRUCTION_ERROR
107+
|| item->_instruction == CSYNC_INSTRUCTION_IGNORE; // BlacklistedError reuses IGNORE
108+
QVERIFY(isErrorItem);
109+
const bool isErrorStatus = item->_status == SyncFileItem::SoftError
110+
|| item->_status == SyncFileItem::BlacklistedError;
111+
QVERIFY(isErrorStatus);
112+
}
113+
}
114+
115+
// Regression: non-quota new files in a server-deleted folder must still be deleted locally
116+
void testDeleteDirectoryWithNewFileNoQuotaError()
117+
{
118+
FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
119+
fakeFolder.remoteModifier().remove(QStringLiteral("A"));
120+
fakeFolder.localModifier().insert(QStringLiteral("A/newfile.txt"), 100);
121+
122+
QVERIFY(fakeFolder.syncOnce());
123+
124+
// New local file with no quota blacklist entry must be removed when parent is deleted on server.
125+
QVERIFY(!fakeFolder.currentLocalState().find(QStringLiteral("A/newfile.txt")));
126+
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
127+
}
128+
55129
void issue1329()
56130
{
57131
FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };

0 commit comments

Comments
 (0)