test(sync): tally rows offered to insertNew to prove no double-fetch

The backfiller's "no message fetched twice" claim (full-history + resume tests)
previously rested on the insertNew fake de-duping by id, so a re-fetched page was
silently absorbed and `cached.size == TOTAL` could not fail on it. Count the rows
offered to insertNew BEFORE de-dupe and assert it equals TOTAL - WINDOW, so any
re-request of an already-cached page now fails the test. This isolates the real
boundary-descent guarantee and, unlike a fetchOlderThan call-count, is independent
of BACKFILL_BATCH_SIZE.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 14:33:13 -05:00
co-authored by Claude Opus 4.8
parent ec60348c89
commit a73b6410a2
@@ -65,6 +65,10 @@ class MailBackfillerTest {
private val cached = mutableListOf<MessageEntity>()
private val progress = mutableMapOf<Pair<String, String>, BackfillProgressEntity>()
// Rows offered to insertNew, counted BEFORE de-dupe: a re-fetched page inflates this even
// though `cached` would silently absorb it. Isolates the "no message fetched twice" guarantee.
private var totalOffered = 0
@Before
fun setUp() {
greenMail = GreenMail(ServerSetupTest.SMTP_IMAP)
@@ -96,6 +100,7 @@ class MailBackfillerTest {
while (backfiller.runBackfill() && guard++ < 10) { /* keep going until no more work */ }
assertEquals(TOTAL, distinctCachedUids().size, "backfill must cache every message")
assertEquals(TOTAL - WINDOW, totalOffered, "each backfilled message fetched exactly once")
assertTrue(cached.size > WINDOW, "that is strictly more than the foreground window")
assertEquals(true, progress["acct" to "INBOX"]?.complete)
assertNoDeletes()
@@ -120,7 +125,8 @@ class MailBackfillerTest {
while (resumed.runBackfill() && guard++ < 10) { /* finish */ }
assertEquals(TOTAL, distinctCachedUids().size, "resume completes the full history")
assertEquals(TOTAL, cached.size, "no message is fetched twice")
assertEquals(TOTAL - WINDOW, totalOffered, "no re-fetch across the interruption")
assertEquals(TOTAL, cached.size, "and nothing is double-inserted")
assertNoDeletes()
}
@@ -151,7 +157,9 @@ class MailBackfillerTest {
val messageDao = mockk<MessageDao>(relaxed = true)
coEvery { messageDao.insertNew(any()) } answers {
firstArg<List<MessageEntity>>().forEach { e -> if (cached.none { it.id == e.id }) cached += e }
val batch = firstArg<List<MessageEntity>>()
totalOffered += batch.size // count BEFORE de-dupe (see field)
batch.forEach { e -> if (cached.none { it.id == e.id }) cached += e }
}
coEvery { messageDao.syncedFolders("acct") } answers {
cached.filter { it.inInbox }.map { it.folder }.distinct()