fix bug 462880 update .msf file when server reports 0 existing messages, w/ unit test, r=neil, sr=standard8
authorDavid Bienvenu <bienvenu@nventure.com>
Mon, 01 Feb 2010 10:37:47 -0800
changeset 4802 da4d1c96c0dd74155904ffc99e6cb015ddfa1e8e
parent 4797 49e4963153a2e7e25a0a1534b8d078c4c7505c37
child 4803 72f8afbdda2fd9f38302ef4d475e262b5bb1fc2d
push idunknown
push userunknown
push dateunknown
reviewersneil, standard8
bugs462880
fix bug 462880 update .msf file when server reports 0 existing messages, w/ unit test, r=neil, sr=standard8
mailnews/imap/src/nsImapProtocol.cpp
mailnews/imap/test/unit/test_imapFlagChange.js
mailnews/imap/test/unit/test_syncChanges.js
--- a/mailnews/imap/src/nsImapProtocol.cpp
+++ b/mailnews/imap/src/nsImapProtocol.cpp
@@ -3958,17 +3958,21 @@ void nsImapProtocol::ProcessMailboxUpdat
         highestRecordedUID = mFolderHighestUID;
 
       AppendUid(fetchStr, highestRecordedUID + 1);
       fetchStr.Append(":*");
       FetchMessage(fetchStr, kFlags);      // only new messages please
     }
   }
   else if (!DeathSignalReceived())
+  {
     GetServerStateParser().ResetFlagInfo();
+    // the flag state is empty, but not partial.
+    m_flagState->SetPartialUIDFetch(PR_FALSE);
+  }
 
   if (!DeathSignalReceived())
   {
     nsImapAction imapAction;
     nsresult res = m_runningUrl->GetImapAction(&imapAction);
     if (NS_SUCCEEDED(res) && imapAction == nsIImapUrl::nsImapLiteSelectFolder)
       return;
   }
--- a/mailnews/imap/test/unit/test_imapFlagChange.js
+++ b/mailnews/imap/test/unit/test_imapFlagChange.js
@@ -126,25 +126,22 @@ function run_test()
   // pref tuning: one connection only, turn off notifications
   let prefBranch = Cc["@mozilla.org/preferences-service;1"]
                      .getService(Ci.nsIPrefBranch);
   prefBranch.setBoolPref("mail.biff.play_sound", false);
   prefBranch.setBoolPref("mail.biff.show_alert", false);
   prefBranch.setBoolPref("mail.biff.show_tray_icon", false);
   prefBranch.setBoolPref("mail.biff.animate_dock_icon", false);
 
-  let inbox = gIMAPDaemon.getMailbox("INBOX");
-
   // build up a diverse list of messages
   let messages = [];
   let gMessageGenerator = new MessageGenerator();
   messages = messages.concat(gMessageGenerator.makeMessage());
   gSynthMessage = messages[0];
 
-  let dataUri = 'data:text/plain,' + gSynthMessage.toMessageString();
   let ioService = Cc["@mozilla.org/network/io-service;1"]
                   .getService(Ci.nsIIOService);
   let msgURI =
     ioService.newURI("data:text/plain;base64," +
                      btoa(gSynthMessage.toMessageString()),
                      null, null);
   let imapInbox =  gIMAPDaemon.getMailbox("INBOX")
   gMessage = new imapMessage(msgURI.spec, imapInbox.uidnext++, []);
new file mode 100644
--- /dev/null
+++ b/mailnews/imap/test/unit/test_syncChanges.js
@@ -0,0 +1,155 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Test to ensure that changes made from a different profile/machine
+ * are synced correctly. In particular, we're checking that emptying out
+ * an imap folder on the server makes us delete all the headers from our db.
+ */
+
+var gIMAPDaemon, gServer, gIMAPIncomingServer;
+
+const gIMAPService = Cc["@mozilla.org/messenger/messageservice;1?type=imap"]
+                       .getService(Ci.nsIMsgMessageService);
+
+load("../../mailnews/resources/messageGenerator.js");
+
+var gIMAPInbox;
+var gMessage;
+var gTest;
+var gSecondFolder;
+var gSynthMessage;
+
+const gTestArray =
+[
+  function switchAwayFromInbox() {
+    let rootFolder = gIMAPIncomingServer.rootFolder;
+    gSecondFolder =  rootFolder.getChildNamed("secondFolder")
+                           .QueryInterface(Ci.nsIMsgImapMailFolder);
+
+    // Selecting the second folder will close the cached connection
+    // on the inbox because fake server only supports one connection at a time.
+    //  Then, we can poke at the message on the imap server directly, which
+    // simulates the user changing the message from a different machine,
+    // and Thunderbird discovering the change when it does a flag sync 
+    // upon reselecting the Inbox.
+    gSecondFolder.updateFolderWithListener(null, UrlListener);
+  },
+  function simulateMailboxEmptied() {
+    gMessage.setFlag("\\Deleted");
+    gIMAPDaemon.getMailbox("INBOX").expunge();
+    gIMAPInbox.updateFolderWithListener(null, UrlListener);
+  },
+  function checkMailboxEmpty() {
+    let msgHdr = gIMAPInbox.msgDatabase.getMsgHdrForMessageID(gSynthMessage.messageId);
+    do_check_eq(gIMAPInbox.getTotalMessages(false), 0);
+    doTest(++gTest);
+  },
+];
+
+function run_test()
+{
+  gTest = 0;
+  loadLocalMailAccount();
+
+  /*
+   * Set up an IMAP server.
+   */
+  gIMAPDaemon = new imapDaemon();
+  gServer = makeServer(gIMAPDaemon, "");
+  gIMAPDaemon.createMailbox("secondFolder", {subscribed : true});
+  gIMAPIncomingServer = createLocalIMAPServer();
+  gIMAPIncomingServer.maximumConnectionsNumber = 1;
+
+  // We need an identity so that updateFolder doesn't fail
+  let acctMgr = Cc["@mozilla.org/messenger/account-manager;1"]
+  .getService(Ci.nsIMsgAccountManager);
+  let localAccount = acctMgr.createAccount();
+  let identity = acctMgr.createIdentity();
+  localAccount.addIdentity(identity);
+  localAccount.defaultIdentity = identity;
+  localAccount.incomingServer = gLocalIncomingServer;
+  acctMgr.defaultAccount = localAccount;
+  
+  // Let's also have another account, using the same identity
+  let imapAccount = acctMgr.createAccount();
+  imapAccount.addIdentity(identity);
+  imapAccount.defaultIdentity = identity;
+  imapAccount.incomingServer = gIMAPIncomingServer;
+  
+  // pref tuning: one connection only, turn off notifications
+  let prefBranch = Cc["@mozilla.org/preferences-service;1"]
+                     .getService(Ci.nsIPrefBranch);
+  prefBranch.setBoolPref("mail.biff.play_sound", false);
+  prefBranch.setBoolPref("mail.biff.show_alert", false);
+  prefBranch.setBoolPref("mail.biff.show_tray_icon", false);
+  prefBranch.setBoolPref("mail.biff.animate_dock_icon", false);
+
+
+  let messages = [];
+  let gMessageGenerator = new MessageGenerator();
+  messages = messages.concat(gMessageGenerator.makeMessage());
+  gSynthMessage = messages[0];
+
+  let ioService = Cc["@mozilla.org/network/io-service;1"]
+                  .getService(Ci.nsIIOService);
+  let msgURI =
+    ioService.newURI("data:text/plain;base64," +
+                     btoa(gSynthMessage.toMessageString()),
+                     null, null);
+  let imapInbox =  gIMAPDaemon.getMailbox("INBOX")
+  gMessage = new imapMessage(msgURI.spec, imapInbox.uidnext++, []);
+  imapInbox.addMessage(gMessage);
+  do_test_pending();
+
+  // Get the IMAP inbox...
+  let rootFolder = gIMAPIncomingServer.rootFolder;
+  gIMAPInbox = rootFolder.getFolderWithFlags(Ci.nsMsgFolderFlags.Inbox)
+                         .QueryInterface(Ci.nsIMsgImapMailFolder);
+
+  // update folder to download header.
+  gIMAPInbox.updateFolderWithListener(null, UrlListener);
+}
+
+var UrlListener = 
+{
+  OnStartRunningUrl: function(url) { },
+  OnStopRunningUrl: function(url, rc)
+  {
+    // Check for ok status.
+    do_check_eq(rc, 0);
+    doTest(++gTest);
+  }
+};
+
+function doTest(test)
+{
+  if (test <= gTestArray.length)
+  {
+    dump("Doing test " + test + "\n");
+    gTest = test;
+
+    var testFn = gTestArray[test - 1];
+    // Set a limit of ten seconds; if the notifications haven't arrived by then there's a problem.
+    try {
+      testFn();
+    } catch(ex) {
+      gServer.stop();
+      do_throw ('TEST FAILED ' + ex);
+    }
+  }
+  else
+  {
+    do_timeout_function(1000, endTest);
+  }
+}
+
+function endTest()
+{
+  gIMAPIncomingServer.closeCachedConnections();
+  gServer.stop();
+
+  var thread = gThreadManager.currentThread;
+  while (thread.hasPendingEvents())
+    thread.processNextEvent(true);
+
+  do_test_finished();
+}