From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../imap/test/unit/test_imapHdrChunking.js | 168 +++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 comm/mailnews/imap/test/unit/test_imapHdrChunking.js (limited to 'comm/mailnews/imap/test/unit/test_imapHdrChunking.js') diff --git a/comm/mailnews/imap/test/unit/test_imapHdrChunking.js b/comm/mailnews/imap/test/unit/test_imapHdrChunking.js new file mode 100644 index 0000000000..8fc23e8502 --- /dev/null +++ b/comm/mailnews/imap/test/unit/test_imapHdrChunking.js @@ -0,0 +1,168 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Tests imap msg header download chunking + */ + +var { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); +var { MessageGenerator, MessageScenarioFactory } = ChromeUtils.import( + "resource://testing-common/mailnews/MessageGenerator.jsm" +); +var { PromiseTestUtils } = ChromeUtils.import( + "resource://testing-common/mailnews/PromiseTestUtils.jsm" +); +var { TestUtils } = ChromeUtils.importESModule( + "resource://testing-common/TestUtils.sys.mjs" +); + +/** + * Keep it so that OVERALL_MESSAGES % CHUNKING_SIZE !== 0. + * With a modulo operator for CHUNKING_SIZE and a prime number for + * OVERALL_MESSAGES this should prove that there have been a + * chunking process without being depended on the first chunk. + */ +const CHUNKING_SIZE = 3; +const OVERALL_MESSAGES = 137; + +// Dummy message window so we can say the inbox is open in a window. +var dummyMsgWindow = Cc["@mozilla.org/messenger/msgwindow;1"].createInstance( + Ci.nsIMsgWindow +); + +function FolderIntPropertyChangedListener() { + this._promise = new Promise(resolve => { + this._resolve = resolve; + }); + this._gotNewMailBiff = false; +} + +FolderIntPropertyChangedListener.prototype = { + onFolderIntPropertyChanged(aItem, aProperty, aOldValue, aNewValue) { + if ( + aProperty == "BiffState" && + aNewValue == Ci.nsIMsgFolder.nsMsgBiffState_NewMail + ) { + this._gotNewMailBiff = true; + this._resolve(); + } + }, + get promise() { + return this._promise; + }, + get gotNewMailBiff() { + return this._gotNewMailBiff; + }, +}; + +var gFolderListener = new FolderIntPropertyChangedListener(); +/** Used to store a listener between tasks for inspecting chunking behaviour. */ +var gListener = new PromiseTestUtils.PromiseUrlListener(); + +add_setup(async function () { + Assert.equal( + OVERALL_MESSAGES % CHUNKING_SIZE !== 0, + true, + "const sanity check" + ); + setupIMAPPump(); + // We need to register the dummyMsgWindow so that we'll think the + // Inbox is open in a folder and fetch headers in chunks. + dummyMsgWindow.openFolder = IMAPPump.inbox; + MailServices.mailSession.AddMsgWindow(dummyMsgWindow); + MailServices.mailSession.AddFolderListener( + gFolderListener, + Ci.nsIFolderListener.intPropertyChanged + ); + + // Set chunk size to CHUNKING_SIZE, so we'll have to chain several requests to get + // OVERALL_MESSAGES headers. + Services.prefs.setIntPref("mail.imap.hdr_chunk_size", CHUNKING_SIZE); + // Turn off offline sync to avoid complications in verifying that we can + // run a url after the first header chunk. + Services.prefs.setBoolPref( + "mail.server.server1.autosync_offline_stores", + false + ); +}); + +// Upload messages to the imap fake server Inbox. +add_task(async function uploadImapMessages() { + // make OVERALL_MESSAGES messages + let messageGenerator = new MessageGenerator(); + let scenarioFactory = new MessageScenarioFactory(messageGenerator); + + // build up a list of messages + let messages = []; + messages = messages.concat(scenarioFactory.directReply(OVERALL_MESSAGES)); + + // Add OVERALL_MESSAGES messages with uids 1,2,3...,OVERALL_MESSAGES. + let imapInbox = IMAPPump.daemon.getMailbox("INBOX"); + // Create the ImapMessages and store them on the mailbox. + messages.forEach(function (message) { + let dataUri = Services.io.newURI( + "data:text/plain;base64," + btoa(message.toMessageString()) + ); + imapInbox.addMessage( + new ImapMessage(dataUri.spec, imapInbox.uidnext++, []) + ); + }); + // Do not wait for the listener to finish. + // We want to observe the message batches in the update process. + // updateFolderWithListener with null for nsIMsgWindow makes biff notify. + IMAPPump.inbox.updateFolderWithListener(null, gListener); +}); + +add_task(async function testMessageFetched() { + // If we're really chunking, then the message fetch should have started before + // we finished the updateFolder URL. + await TestUtils.waitForCondition(() => { + return gFolderListener.gotNewMailBiff === true; + }); + Assert.ok(gFolderListener.gotNewMailBiff); + + // We do not check for the first chunk as this is unreliable without explicit + // listeners/events. + // Instead we are checking if there's no rest of the division with + // CHUNKING_SIZE while the chunking process is ongoing. + // It's important that the chunking is intact and as well not failing + // randomly in the test infrastructure. + // See at the CHUNKING_SIZE and OVERALL_MESSAGES declarations. + // + // HINT: + // If this causes future problems because stuff getting faster, + // try to increase the overall message count. + await TestUtils.waitForCondition(() => { + let messagesDBFolder = IMAPPump.inbox.msgDatabase.dBFolderInfo.numMessages; + if (messagesDBFolder !== 0) { + Assert.equal( + messagesDBFolder % CHUNKING_SIZE, + 0, + `${messagesDBFolder} messages in folder should be of chunk size ${CHUNKING_SIZE}` + ); // This is the primary test. + return true; + } else if (messagesDBFolder === OVERALL_MESSAGES) { + throw new Error( + `Batching failed in sizes of ${CHUNKING_SIZE} found instead ${OVERALL_MESSAGES} immediately` + ); + } + return false; // Rerun waitForCondition. + }, 50); +}); + +add_task(async function testHdrsDownloaded() { + await gListener.promise; // Now we wait for the finished update of the Folder. + // Make sure that we got all OVERALL_MESSAGES headers. + Assert.equal( + IMAPPump.inbox.msgDatabase.dBFolderInfo.numMessages, + OVERALL_MESSAGES + ); +}); + +// Cleanup +add_task(async function endTest() { + teardownIMAPPump(); +}); -- cgit v1.2.3