    def _replacement_with_reused_rowids(self):
        replacement = self.account / 'rowids-reused.tmp'
        db = sqlite3.connect(replacement)
        try:
            db.execute('CREATE TABLE message_table(sender_id TEXT,conversation_id TEXT,content_type INTEGER,send_time INTEGER,content BLOB,server_id TEXT,client_id TEXT)')
            db.executemany('INSERT INTO message_table VALUES(?,?,?,?,?,?,?)',
                           [('other', 'M:999', 2, 900 + i, 'OTHER CONVERSATION PRIVATE BODY', f'other-{i}', '') for i in range(3)])
            db.commit()
        finally:
            db.close()
        return replacement

    def test_database_replaced_between_index_and_message_read_cannot_leak_conversation(self):
        browser._message_index(self.database)
        replacement = self._replacement_with_reused_rowids()
        original = browser._read_message_rows
        def replace_before_read(*args, **kwargs):
            os.replace(replacement, self.database)
            return original(*args, **kwargs)
        with mock.patch.object(browser, '_read_message_rows', side_effect=replace_before_read):
            messages = browser._messages(self.database, '100', 'M:200', {}, 12)
        self.assertEqual(messages, [])
        refreshed = self.snapshot()
        self.assertEqual(refreshed['selectedConversation'], 'M:999')

    def test_database_replaced_between_index_and_preview_read_cannot_leak_conversation(self):
        browser._message_index(self.database)
        replacement = self._replacement_with_reused_rowids()
        original = browser._read_message_rows
        def replace_before_read(*args, **kwargs):
            os.replace(replacement, self.database)
            return original(*args, **kwargs)
        with mock.patch.object(browser, '_read_message_rows', side_effect=replace_before_read):
            rows, _, _ = browser._conversation_rows(self.database, '100', {}, {}, '', 8)
        self.assertTrue(rows)
        self.assertTrue(all(item['preview'] == '' for item in rows))

