You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ma...@apache.org on 2009/12/18 13:25:18 UTC

svn commit: r892238 - in /james/hupa/trunk/server/src: main/java/org/apache/hupa/server/InMemoryIMAPStoreCache.java test/java/org/apache/hupa/server/integration/ test/java/org/apache/hupa/server/integration/StoreBugTest.java

Author: manolo
Date: Fri Dec 18 12:25:17 2009
New Revision: 892238

URL: http://svn.apache.org/viewvc?rev=892238&view=rev
Log:
Fixed HUPA-57

Added:
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/integration/
    james/hupa/trunk/server/src/test/java/org/apache/hupa/server/integration/StoreBugTest.java
Modified:
    james/hupa/trunk/server/src/main/java/org/apache/hupa/server/InMemoryIMAPStoreCache.java

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/InMemoryIMAPStoreCache.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/InMemoryIMAPStoreCache.java?rev=892238&r1=892237&r2=892238&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/InMemoryIMAPStoreCache.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/InMemoryIMAPStoreCache.java Fri Dec 18 12:25:17 2009
@@ -180,7 +180,6 @@
         }
         
         public void validate() throws MessagingException {
-            store.idle();
             validUntil = System.currentTimeMillis() + validForMillis;
         }
         

Added: james/hupa/trunk/server/src/test/java/org/apache/hupa/server/integration/StoreBugTest.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/test/java/org/apache/hupa/server/integration/StoreBugTest.java?rev=892238&view=auto
==============================================================================
--- james/hupa/trunk/server/src/test/java/org/apache/hupa/server/integration/StoreBugTest.java (added)
+++ james/hupa/trunk/server/src/test/java/org/apache/hupa/server/integration/StoreBugTest.java Fri Dec 18 12:25:17 2009
@@ -0,0 +1,249 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.hupa.server.integration;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Properties;
+
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+
+import junit.framework.Assert;
+
+import org.apache.hupa.server.InMemoryIMAPStoreCache;
+import org.apache.hupa.server.guice.SessionProvider;
+import org.apache.hupa.server.mock.MockIMAPStore;
+import org.apache.hupa.server.mock.MockLog;
+import org.apache.hupa.shared.data.User;
+import org.junit.Test;
+
+import com.sun.mail.imap.IMAPFolder;
+import com.sun.mail.imap.IMAPStore;
+
+public class StoreBugTest {
+    
+    static final String imapServer = "imap.gmail.com";
+    static final int imapPort = 993;
+    static final String imapUser = "nobody@gmail.com";
+    static final String imapPass = "******";
+    static final boolean isSSl = true;
+    
+    static int nthreads = 5;
+    static int threadTimeout = 15000;
+    
+    Session session = Session.getDefaultInstance(new Properties(), null);
+    static InMemoryIMAPStoreCache cache = new InMemoryIMAPStoreCache(new MockLog(), imapServer, imapPort, isSSl, 2, 60000, new SessionProvider());
+    static User user = new User() {
+       private static final long serialVersionUID = 1L;
+       {setName(imapUser); setPassword(imapPass);}
+    };
+    
+    @Test 
+    public void testMockIMAPStore() throws Exception {
+        TestThread[] threads = testIMAPStoreIdle(getStore(true), "Demo-Inbox", 100);
+        Assert.assertNotNull(threads);
+        Assert.assertFalse(getThreadsSpentTime(threads).contains("-1"));
+    }
+
+    @Test 
+    public void testIMAPStoreIdleHungs() throws Exception {
+        IMAPStore store = null;
+        try {
+            store = getStore(false);
+        } catch (Exception e) {
+            Throwable t = e;
+            while (e.getCause() != null) t = e.getCause();
+            String msg = t.getClass().getName() + " " + t.getMessage();
+            System.out.println("Skipping integration test: " + msg);
+            return;
+        }
+        TestThread[] threads = testIMAPStoreIdle(store, "INBOX", 30000);
+        if (threads == null)
+            return;
+        System.out.println(getThreadsSpentTime(threads));
+        Assert.assertTrue(getThreadsSpentTime(threads).contains("-1"));
+    }
+
+    public TestThread[] testIMAPStoreIdle(final IMAPStore store, final String folder, int timeout) throws Exception {
+        // Start the threads
+        TestThread[] threads = new TestThread[nthreads];
+        for (int i = 0; i<nthreads; i++) {
+            TestThread t = new TestThread(){
+                void execute() throws Exception {
+                    store.idle();
+                    executeSomeFolderOperations(store, folder);
+                }
+            };
+            threads[i] = t;
+            t.start();
+        }
+
+        // wait until all threads have finished
+        waitForThreads(threads, timeout);
+        return threads;
+    }
+
+    @Test  
+    public void testInMemoryImapStoreCacheDoesntHung() throws Exception {
+        try {
+            cache.get(user);
+        } catch (Exception e) {
+            Throwable t = e;
+            while (e.getCause() != null) t = e.getCause();
+            String msg = t.getClass().getName() + " " + t.getMessage();
+            System.out.println("Skipping integration test: " + msg);
+            return;
+        }
+        
+        // Start the threads
+        TestThread[] threads = new TestThread[10];
+        for (int i = 0; i<threads.length; i++) {
+            TestThread t = new TestThread(){
+                void execute() throws Exception {
+                  IMAPStore store =   cache.get(user);
+                  String folder = "INBOX";
+                  executeSomeFolderOperations(store, folder);
+                }
+            };
+            threads[i] = t;
+            t.start();
+        }
+
+        // wait until all threads have finished
+        waitForThreads(threads, 30000);
+        
+        Assert.assertFalse(getThreadsSpentTime(threads).contains("-1"));
+    }
+
+    private abstract class TestThread extends Thread {
+        public long spent_millisecs = -1;
+        abstract void execute() throws Exception;
+        public void run() {
+            try {
+                long start = System.nanoTime();
+                execute();
+                long end = System.nanoTime();
+                long diff_nanosecs = end - start;
+                long diff_millsecs = diff_nanosecs/1000000;
+                spent_millisecs = diff_millsecs;
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private void executeSomeFolderOperations(IMAPStore store, String folder) throws MessagingException, IOException {
+        final IMAPFolder inbox = (IMAPFolder) store.getFolder(folder);
+        inbox.open(IMAPFolder.READ_WRITE);
+        // count the number of messages in the inbox
+        int count = inbox.getMessageCount();
+        // get the list of messages
+        Message[] messages = inbox.getMessages(1, count);
+        // get a randomly selected message in the list
+        Message msg = messages[getRandom(1, count)];
+        // download the message from the server
+        long uid = inbox.getUID(msg);
+        Message message = inbox.getMessageByUID(uid);
+        // write it to a null stream
+        message.writeTo(devNull);
+    }
+    
+    // Create a new imap store connection (mock or real)
+    private IMAPStore getStore(boolean mock) throws Exception {
+        IMAPStore store = null;
+        if (mock) {
+            store = new MockIMAPStore(session);
+        } else {
+            // Configure session
+            session.setDebug(false);
+            Properties props = session.getProperties();
+            props.setProperty("mail.mime.decodetext.strict", "false");
+            props.setProperty("mail.imap.connectionpoolsize", 2 + "");
+            props.setProperty("mail.imap.connectionpooltimeout", 30000 + "");
+            props.setProperty("mail.imaps.connectionpoolsize", 2 + "");
+            props.setProperty("mail.imaps.connectionpooltimeout", 30000 + "");
+            System.setProperty("mail.mime.decodetext.strict", "false");        
+            // Create the imap connection
+            store = (IMAPStore)session.getStore(isSSl ? "imaps" : "imap");
+            store.connect(imapServer, imapPort, imapUser, imapPass);
+        }
+        return store;
+    }
+    
+    @SuppressWarnings("deprecation")
+    void waitForThreads(TestThread[] threads, int timeout) throws Exception {
+        long start = System.currentTimeMillis();
+        while(true) {
+            boolean done = true;
+            long ellapsed = System.currentTimeMillis() - start;
+            for (TestThread t : threads) {
+                t.join(1);
+                if (t.isAlive())
+                    done = false;
+
+                if (ellapsed > timeout)  {
+                    t.stop();
+                    t.interrupt();
+                }
+                if (ellapsed > (timeout + 4000)) {
+                    System.out.println("It seems there are locked threads.");
+                    return;
+                }
+            }
+            if (done)
+                break;
+            Thread.sleep(100);
+        }
+    }
+    
+    String getThreadsStatus(TestThread[] threads){
+        String ret = "";
+        for (TestThread t : threads) {
+            if (t.isAlive())
+                ret += " ACT";
+            else if (t.isInterrupted())
+                ret += " INT";
+            else if (t.spent_millisecs < 0)
+                ret += " ERR";
+            else
+                ret += " OK ";
+        }
+        return ret;
+    }
+
+    String getThreadsSpentTime(TestThread[] threads){
+        String ret = "";
+        for (TestThread t : threads) 
+            ret += " " + t.spent_millisecs;
+        return ret;
+    }
+   
+    int getRandom(int floor, int ceil) {
+        return floor + (int)(Math.random() * Math.abs(ceil -floor));
+    }
+    
+    OutputStream devNull = new OutputStream() {
+        public void write(int b) throws IOException {
+        }
+    };
+    
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org