diff options
Diffstat (limited to '')
-rw-r--r-- | comm/mailnews/local/test/unit/test_pop3ServerBrokenCRAMDisconnect.js | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/comm/mailnews/local/test/unit/test_pop3ServerBrokenCRAMDisconnect.js b/comm/mailnews/local/test/unit/test_pop3ServerBrokenCRAMDisconnect.js new file mode 100644 index 0000000000..ff13870352 --- /dev/null +++ b/comm/mailnews/local/test/unit/test_pop3ServerBrokenCRAMDisconnect.js @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/** + * Server which advertises CRAM-MD5, but is impolite enough to just + * disconnect (close the TCP connection) when we try it. + * + * This is a tough one, because we may lose state on which auth schemes + * are allowed and which ones failed and may restart from scratch, and + * retry, never skipping the failed scheme. + * Dear server implementors, NEVER DO THAT! Be polite, give an error + * with explanation and by all means keep the connection open. + * + * I don't know if real servers do that, but bienvenu says they exist. + * + * TODO: + * This test shows that the current situation is not good. + * Problems: + * - We should reopen the connection, remember which auth scheme failed + * and start with the next in list, not trying the broken one again. + * We currently neither retry nor remember. + * - incomingServer thinks it is still running/busy although the connection is + * clearly done and over. + * + * @author Ben Bucksch + */ + +var server; +var daemon; +var incomingServer; +test = + "Server which advertises CRAM-MD5, but closes the connection when it's tried"; +// that's how it currently looks like (we fail to log in): +var expectedTransaction = ["AUTH", "CAPA", "AUTH CRAM-MD5"]; +// TODO that's how it should look like (we start a new connection and try another scheme): +// const expectedTransaction = ["AUTH", "CAPA", "AUTH CRAM-MD5", "CAPA", "AUTH PLAIN", "STAT"]; + +var urlListener = { + OnStartRunningUrl(url) {}, + OnStopRunningUrl(url, result) { + try { + // We should be getting an error here, because we couldn't log in. + Assert.equal(result, Cr.NS_ERROR_FAILURE); + + var transaction = server.playTransaction(); + do_check_transaction(transaction, expectedTransaction); + + do_timeout(0, endTest); + } catch (e) { + server.stop(); + var thread = gThreadManager.currentThread; + while (thread.hasPendingEvents()) { + thread.processNextEvent(true); + } + + do_throw(e); + } + }, +}; + +function endTest() { + // No more tests, let everything finish + server.stop(); + + var thread = gThreadManager.currentThread; + while (thread.hasPendingEvents()) { + thread.processNextEvent(true); + } + + do_test_finished(); +} + +function CRAMFail_handler(daemon_) { + POP3_RFC5034_handler.call(this, daemon_); + + this._kAuthSchemeStartFunction["CRAM-MD5"] = this.killConn; +} +CRAMFail_handler.prototype = { + __proto__: POP3_RFC5034_handler.prototype, // inherit + + killConn() { + this.closing = true; + return "-ERR I don't feel like it"; + }, +}; + +function run_test() { + try { + do_test_pending(); + + // Disable new mail notifications + Services.prefs.setBoolPref("mail.biff.play_sound", false); + Services.prefs.setBoolPref("mail.biff.show_alert", false); + Services.prefs.setBoolPref("mail.biff.show_tray_icon", false); + Services.prefs.setBoolPref("mail.biff.animate_dock_icon", false); + + daemon = new Pop3Daemon(); + function createHandler(d) { + return new CRAMFail_handler(d); + } + server = new nsMailServer(createHandler, daemon); + server.start(); + + incomingServer = createPop3ServerAndLocalFolders(server.port); + let msgServer = incomingServer; + msgServer.QueryInterface(Ci.nsIMsgIncomingServer); + // Need to allow any auth here, although that's not use in TB really, + // because we need to fall back to something after CRAM-MD5 and + // check that login works after we fell back. + msgServer.authMethod = Ci.nsMsgAuthMethod.anything; + + MailServices.pop3.GetNewMail( + null, + urlListener, + localAccountUtils.inboxFolder, + incomingServer + ); + server.performTest(); + } catch (e) { + server.stop(); + + do_throw(e); + } finally { + var thread = gThreadManager.currentThread; + while (thread.hasPendingEvents()) { + thread.processNextEvent(true); + } + } +} |