diff options
Diffstat (limited to '')
-rw-r--r-- | comm/mailnews/news/test/unit/test_internalUris.js | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/comm/mailnews/news/test/unit/test_internalUris.js b/comm/mailnews/news/test/unit/test_internalUris.js new file mode 100644 index 0000000000..4be0402f0e --- /dev/null +++ b/comm/mailnews/news/test/unit/test_internalUris.js @@ -0,0 +1,305 @@ +/* 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 internal URIs generated by various methods in the code base. + * If you manually generate a news URI somewhere, please add it to this test. + */ + +Cu.importGlobalProperties(["crypto"]); + +/* import-globals-from ../../../test/resources/alertTestUtils.js */ +load("../../../resources/alertTestUtils.js"); + +var { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); +var { PromiseTestUtils } = ChromeUtils.import( + "resource://testing-common/mailnews/PromiseTestUtils.jsm" +); +var { PromiseUtils } = ChromeUtils.importESModule( + "resource://gre/modules/PromiseUtils.sys.mjs" +); + +var daemon, localserver, server; + +var kCancelArticle = + "From: fake@acme.invalid\n" + + "Newsgroups: test.filter\n" + + "Subject: cancel <4@regular.invalid>\n" + + "References: <4@regular.invalid>\n" + + "Control: cancel <4@regular.invalid>\n" + + "MIME-Version: 1.0\n" + + "Content-Type: text/plain\n" + + "\n" + + "This message was cancelled from within "; + +var dummyMsgWindow; + +add_setup(function setupTest() { + registerAlertTestUtils(); + + daemon = setupNNTPDaemon(); + server = makeServer(NNTP_RFC2980_handler, daemon); + server.start(); + localserver = setupLocalServer(server.port); + + // Set up an identity for posting. + let identity = MailServices.accounts.createIdentity(); + identity.fullName = "Normal Person"; + identity.email = "fake@acme.invalid"; + MailServices.accounts.FindAccountForServer(localserver).addIdentity(identity); + + dummyMsgWindow = new DummyMsgWindow(); +}); + +add_task(async function test_newMsgs() { + // This tests nsMsgNewsFolder::GetNewsMessages via getNewMessages. + let folder = localserver.rootFolder.getChildNamed("test.filter"); + Assert.equal(folder.getTotalMessages(false), 0); + let urlListener = new PromiseTestUtils.PromiseUrlListener(); + folder.getNewMessages(null, urlListener); + await urlListener.promise; + Assert.equal(folder.getTotalMessages(false), 8); +}); + +add_task(async function test_cancel() { + // This tests nsMsgNewsFolder::CancelMessage. + let folder = localserver.rootFolder.getChildNamed("test.filter"); + let db = folder.msgDatabase; + let hdr = db.getMsgHdrForKey(4); + + folder.QueryInterface(Ci.nsIMsgNewsFolder).cancelMessage(hdr, dummyMsgWindow); + await dummyMsgWindow.promise; + + // Reset promise state. + dummyMsgWindow.deferPromise(); + + Assert.equal(folder.getTotalMessages(false), 7); + + // Check the content of the CancelMessage itself. + let article = daemon.getGroup("test.filter")[9]; + // Since the cancel message includes the brand name (Daily, Thunderbird), we + // only check the beginning of the string. + Assert.ok(article.fullText.startsWith(kCancelArticle)); +}); + +function generateLongArticle() { + // After converting to base64, the message body will be 65536 * 4 = 256KB. + let arr = new Uint8Array(65536); + crypto.getRandomValues(arr); + return `Date: Mon, 23 Jun 2008 19:58:07 +0400 +From: Normal Person <fake@acme.invalid> +MIME-Version: 1.0 +Subject: Odd Subject +Content-Type: text/plain; charset=ISO-8859-1; format=flowed +Content-Transfer-Encoding: 7bit +Message-ID: <2@regular.invalid> + +${btoa(arr)} +${btoa(arr)} +${btoa(arr)} +`; +} + +add_task(async function test_fetchMessage() { + // Replace the second article with a large message. + daemon.addArticleToGroup( + new NewsArticle(generateLongArticle()), + "test.filter", + 2 + ); + + // Tests nsNntpService::CreateMessageIDURL via FetchMessage. + let streamListener = new PromiseTestUtils.PromiseStreamListener(); + let urlListener = new PromiseTestUtils.PromiseUrlListener(); + let folder = localserver.rootFolder.getChildNamed("test.filter"); + MailServices.nntp.fetchMessage(folder, 2, null, streamListener, urlListener); + await urlListener.promise; + let data = await streamListener.promise; + // To point out that the streamListener Promise shouldn't reject. + Assert.ok(data); +}); + +add_task(async function test_fetchMessageNoStreamListener() { + // Tests nsNntpService::CreateMessageIDURL via FetchMessage. + let streamListener = null; + let urlListener = new PromiseTestUtils.PromiseUrlListener(); + let folder = localserver.rootFolder.getChildNamed("test.filter"); + MailServices.nntp.fetchMessage(folder, 2, null, streamListener, urlListener); + await urlListener.promise; +}); + +add_task(async function test_search() { + // This tests nsNntpService::Search. + let folder = localserver.rootFolder.getChildNamed("test.filter"); + var searchSession = Cc[ + "@mozilla.org/messenger/searchSession;1" + ].createInstance(Ci.nsIMsgSearchSession); + searchSession.addScopeTerm(Ci.nsMsgSearchScope.news, folder); + + let searchTerm = searchSession.createTerm(); + searchTerm.attrib = Ci.nsMsgSearchAttrib.Subject; + let value = searchTerm.value; + value.str = "First"; + searchTerm.value = value; + searchTerm.op = Ci.nsMsgSearchOp.Contains; + searchTerm.booleanAnd = false; + searchSession.appendTerm(searchTerm); + + let hitCount; + let searchListener = new PromiseTestUtils.PromiseSearchNotify(searchSession, { + onSearchHit() { + hitCount++; + }, + onNewSearch() { + hitCount = 0; + }, + }); + + searchSession.search(null); + await searchListener.promise; + + Assert.equal(hitCount, 1); +}); + +add_task(async function test_grouplist() { + // This tests nsNntpService::GetListOfGroupsOnServer. + let subserver = localserver.QueryInterface(Ci.nsISubscribableServer); + let subscribablePromise = PromiseUtils.defer(); + let subscribeListener = { + OnDonePopulating() { + subscribablePromise.resolve(); + }, + }; + subserver.subscribeListener = subscribeListener; + + function enumGroups(rootUri) { + let hierarchy = subserver.getChildURIs(rootUri); + let groups = []; + for (let name of hierarchy) { + if (subserver.isSubscribable(name)) { + groups.push(name); + } + if (subserver.hasChildren(name)) { + groups = groups.concat(enumGroups(name)); + } + } + return groups; + } + + MailServices.nntp.getListOfGroupsOnServer(localserver, null, false); + await subscribablePromise.promise; + + let groups = enumGroups(""); + Assert.equal(groups.length, Object.keys(daemon._groups).length); + for (let group in daemon._groups) { + Assert.ok(groups.includes(group)); + } + + // First node in the group list, even though it is not subscribable, + // parent of "test.empty" group. + Assert.equal(subserver.getFirstChildURI(""), "test"); + + // Release reference, somehow impedes GC of 'subserver'. + subserver.subscribeListener = null; +}); + +add_task(async function test_postMessage() { + // This tests nsNntpService::SetUpNntpUrlForPosting via PostMessage. + let urlListener = new PromiseTestUtils.PromiseUrlListener(); + MailServices.nntp.postMessage( + do_get_file("postings/post2.eml"), + "misc.test", + localserver.key, + urlListener, + null + ); + await urlListener.promise; + Assert.equal(daemon.getGroup("misc.test").keys.length, 1); +}); + +// Not tested because it requires UI, and this is insufficient, I think. +// function test_forwardInline() { +// // This tests mime_parse_stream_complete via forwarding inline +// let folder = localserver.rootFolder.getChildNamed("test.filter"); +// let hdr = folder.msgDatabase.getMsgHdrForKey(1); +// MailServices.compose.forwardMessage("a@b.invalid", hdr, null, +// localserver, Ci.nsIMsgComposeService.kForwardInline); +// } + +add_task(async function test_escapedName() { + // This does a few tests to make sure our internal URIs work for newsgroups + // with names that need escaping. + let evilName = "test.malformed&name"; + daemon.addGroup(evilName); + daemon.addArticle(make_article(do_get_file("postings/bug670935.eml"))); + localserver.subscribeToNewsgroup(evilName); + + // Can we access it? + let folder = localserver.rootFolder.getChildNamed(evilName); + let newMessageUrlListener = new PromiseTestUtils.PromiseUrlListener(); + folder.getNewMessages(null, newMessageUrlListener); + await newMessageUrlListener.promise; + + // If we get here, we didn't crash--newsgroups unescape properly. + // Load a message, to test news-message: URI unescaping. + let streamlistener = new PromiseTestUtils.PromiseStreamListener(); + let fetchMessageUrlListener = new PromiseTestUtils.PromiseUrlListener(); + MailServices.nntp.fetchMessage( + folder, + 1, + null, + streamlistener, + fetchMessageUrlListener + ); + await fetchMessageUrlListener.promise; + let data = await streamlistener.promise; + // To point out that the streamListener Promise shouldn't reject. + Assert.ok(data); +}); + +add_task(function cleanUp() { + localserver.closeCachedConnections(); +}); + +class DummyMsgWindow { + QueryInterface = ChromeUtils.generateQI([ + "nsIMsgWindow", + "nsISupportsWeakReference", + ]); + + constructor() { + this._deferredPromise = PromiseUtils.defer(); + } + + get statusFeedback() { + let scopedThis = this; + return { + startMeteors() {}, + stopMeteors() { + scopedThis._deferredPromise.resolve(true); + }, + showProgress() {}, + }; + } + + get promptDialog() { + return alertUtilsPrompts; + } + + deferPromise() { + this._deferredPromise = PromiseUtils.defer(); + } + + get promise() { + return this._deferredPromise.promise; + } +} + +/* exported alert, confirmEx */ +// Prompts for cancel. +function alertPS(parent, title, text) {} +function confirmExPS(parent, title, text, flags) { + return 0; +} |