196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/*
296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *
496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * you may not use this file except in compliance with the License.
696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * You may obtain a copy of the License at
796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *
896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *
1096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * See the License for the specific language governing permissions and
1496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * limitations under the License.
1596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */
1696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
1796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectpackage com.android.email.mail.store;
1896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
19cb1d65c47825dc7a45c7954cd93669296b35305eBen Komaloimport android.content.Context;
20cb1d65c47825dc7a45c7954cd93669296b35305eBen Komaloimport android.test.AndroidTestCase;
21627bc6ed57ee06cc588e64ff959bfd7870b659b6Marc Blankimport android.test.suitebuilder.annotation.SmallTest;
227037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xieimport android.test.suitebuilder.annotation.Suppress;
23627bc6ed57ee06cc588e64ff959bfd7870b659b6Marc Blank
24cb1d65c47825dc7a45c7954cd93669296b35305eBen Komaloimport com.android.email.DBTestHelper;
2596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport com.android.email.mail.transport.MockTransport;
26cb1d65c47825dc7a45c7954cd93669296b35305eBen Komaloimport com.android.email.provider.ProviderTestUtils;
2731d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blankimport com.android.emailcommon.TempDirectory;
282193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.internet.MimeMessage;
292193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Address;
302193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.FetchProfile;
312193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Flag;
322193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Folder;
332193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Folder.FolderType;
342193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Folder.OpenMode;
3531d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blankimport com.android.emailcommon.mail.Message;
362193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Message.RecipientType;
3731d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blankimport com.android.emailcommon.mail.MessagingException;
38f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport com.android.emailcommon.provider.Account;
3912b82d9374947c9268217f45befe8a74bd9b60d7Ben Komaloimport com.android.emailcommon.provider.HostAuth;
4096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
4196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/**
4296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * This is a series of unit tests for the POP3 Store class.  These tests must be locally
4396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * complete - no server(s) required.
4496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */
457037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie@Suppress
4696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project@SmallTest
47cb1d65c47825dc7a45c7954cd93669296b35305eBen Komalopublic class Pop3StoreUnitTests extends AndroidTestCase {
4896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    final String UNIQUE_ID_1 = "20080909002219r1800rrjo9e00";
49a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
5096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    final static int PER_MESSAGE_SIZE = 100;
51a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
5296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /* These values are provided by setUp() */
5396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private Pop3Store mStore = null;
5496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private Pop3Store.Pop3Folder mFolder = null;
55a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
56cb1d65c47825dc7a45c7954cd93669296b35305eBen Komalo    private Context mMockContext;
5717d3a29c9d8f7a27c463239f190bdcc4e0804527Jerry Xie    private HostAuth mHostAuth;
58cb1d65c47825dc7a45c7954cd93669296b35305eBen Komalo
5996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
6096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Setup code.  We generate a lightweight Pop3Store and Pop3Store.Pop3Folder.
6196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
6296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    @Override
6396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    protected void setUp() throws Exception {
6496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        super.setUp();
65cb1d65c47825dc7a45c7954cd93669296b35305eBen Komalo        mMockContext = DBTestHelper.ProviderContextSetupHelper.getProviderContext(
66cb1d65c47825dc7a45c7954cd93669296b35305eBen Komalo                getContext());
67cb1d65c47825dc7a45c7954cd93669296b35305eBen Komalo
68a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy        // Use the target's (i.e. the Email application) context
69cb1d65c47825dc7a45c7954cd93669296b35305eBen Komalo        TempDirectory.setTempDirectory(mMockContext);
700a8030562a5235591a5f5364bf5e6855ffa62861Makoto Onuki
7196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // These are needed so we can get at the inner classes
7217d3a29c9d8f7a27c463239f190bdcc4e0804527Jerry Xie        mHostAuth = new HostAuth();
73cb1d65c47825dc7a45c7954cd93669296b35305eBen Komalo        Account testAccount = ProviderTestUtils.setupAccount("acct1", false, mMockContext);
74a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
7517d3a29c9d8f7a27c463239f190bdcc4e0804527Jerry Xie        mHostAuth.setLogin("user", "password");
7617d3a29c9d8f7a27c463239f190bdcc4e0804527Jerry Xie        mHostAuth.setConnection("pop3", "server", 999);
7717d3a29c9d8f7a27c463239f190bdcc4e0804527Jerry Xie        testAccount.mHostAuthRecv = mHostAuth;
78cb1d65c47825dc7a45c7954cd93669296b35305eBen Komalo        testAccount.save(mMockContext);
79cb1d65c47825dc7a45c7954cd93669296b35305eBen Komalo        mStore = (Pop3Store) Pop3Store.newInstance(testAccount, mMockContext);
8096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mFolder = (Pop3Store.Pop3Folder) mStore.getFolder("INBOX");
8196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
8296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
8396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
8496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Test various sunny-day operations of UIDL parser for multi-line responses
8596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
8696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void testUIDLParserMulti() {
8796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
8896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // multi-line mode
8996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Pop3Store.Pop3Folder.UidlParser parser = mFolder.new UidlParser();
90a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
9196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // Test basic in-list UIDL
9296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        parser.parseMultiLine("101 " + UNIQUE_ID_1);
9396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(101, parser.mMessageNumber);
9496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(UNIQUE_ID_1, parser.mUniqueId);
9596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertFalse(parser.mEndOfMessage);
9696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertFalse(parser.mErr);
97a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
9896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        //  Test end-of-list
9996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        parser.parseMultiLine(".");
10096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertTrue(parser.mEndOfMessage);
10196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertFalse(parser.mErr);
10296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
103a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
10496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
10596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Test various sunny-day operations of UIDL parser for single-line responses
10696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
107a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy    public void testUIDLParserSingle() {
10896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
10996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // single-line mode
11096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Pop3Store.Pop3Folder.UidlParser parser = mFolder.new UidlParser();
11196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
11296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // Test single-message OK response
11396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        parser.parseSingleLine("+OK 101 " + UNIQUE_ID_1);
11496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(101, parser.mMessageNumber);
11596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(UNIQUE_ID_1, parser.mUniqueId);
11696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertTrue(parser.mEndOfMessage);
117a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
11896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // Test single-message ERR response
11996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        parser.parseSingleLine("-ERR what???");
12096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertTrue(parser.mErr);
12196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
122a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
12396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
124b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler     * Test various rainy-day operations of the UIDL parser for multi-line responses
125b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler     * TODO other malformed responses
126b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler     */
127b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler    public void testUIDLParserMultiFail() {
128b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        // multi-line mode
129b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        Pop3Store.Pop3Folder.UidlParser parser = mFolder.new UidlParser();
130a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
131b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        // Test with null input
132b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        boolean result;
133b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        result = parser.parseMultiLine(null);
134b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        assertFalse(result);
135a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
136b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        // Test with empty input
137b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        result = parser.parseMultiLine("");
138b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        assertFalse(result);
139b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler    }
140a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
141b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler    /**
142b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler     * Test various rainy-day operations of the UIDL parser for single-line responses
143b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler     * TODO other malformed responses
144b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler     */
145b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler    public void testUIDLParserSingleFail() {
146b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        // single-line mode
147b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        Pop3Store.Pop3Folder.UidlParser parser = mFolder.new UidlParser();
148a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
149b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        // Test with null input
150b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        boolean result;
151b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        result = parser.parseSingleLine(null);
152b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        assertFalse(result);
153a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
154b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        // Test with empty input
155b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        result = parser.parseSingleLine("");
156b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        assertFalse(result);
157b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler    }
158a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
159b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler    /**
16096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Tests that variants on the RFC-specified formatting of UIDL work properly.
16196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
16296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void testUIDLComcastVariant() {
163a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
16496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // multi-line mode
16596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Pop3Store.Pop3Folder.UidlParser parser = mFolder.new UidlParser();
166a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
16796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // Comcast servers send multiple spaces in their darn UIDL strings.
16896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        parser.parseMultiLine("101   " + UNIQUE_ID_1);
16996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(101, parser.mMessageNumber);
17096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(UNIQUE_ID_1, parser.mUniqueId);
17196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertFalse(parser.mEndOfMessage);
17296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertFalse(parser.mErr);
17396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
174a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
17596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
17696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Confirms simple non-SSL non-TLS login
17796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
17896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void testSimpleLogin() throws MessagingException {
179a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
18096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        MockTransport mockTransport = openAndInjectMockTransport();
181a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
18296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // try to open it
18396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        setupOpenFolder(mockTransport, 0, null);
184244d306ebb0addbc5d87008af9412b76c80e861eMarc Blank        mFolder.open(OpenMode.READ_ONLY);
18596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
186a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
18796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
18896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * TODO: Test with SSL negotiation (faked)
18996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * TODO: Test with SSL required but not supported
19096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * TODO: Test with TLS negotiation (faked)
19196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * TODO: Test with TLS required but not supported
19296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * TODO: Test calling getMessageCount(), getMessages(), etc.
19396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
194a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
19596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
19696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Test the operation of checkSettings(), which requires (a) a good open and (b) UIDL support.
19796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
19896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void testCheckSettings() throws MessagingException {
19996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
20096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        MockTransport mockTransport = openAndInjectMockTransport();
201a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
20296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // scenario 1:  CAPA returns -ERR, so we try UIDL explicitly
20396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        setupOpenFolder(mockTransport, 0, null);
20496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        setupUidlSequence(mockTransport, 1);
20596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mockTransport.expect("QUIT", "");
20696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mStore.checkSettings();
207a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
20896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // scenario 2:  CAPA indicates UIDL, so we don't try UIDL
20996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        setupOpenFolder(mockTransport, 0, "UIDL");
21096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mockTransport.expect("QUIT", "");
21196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mStore.checkSettings();
212a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
21396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // scenario 3:  CAPA returns -ERR, and UIDL fails
21496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        try {
21596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            setupOpenFolder(mockTransport, 0, null);
21696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mockTransport.expect("UIDL", "-ERR unsupported");
21796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mockTransport.expect("QUIT", "");
21896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mStore.checkSettings();
21996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            fail("MessagingException was expected due to UIDL unsupported.");
22096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        } catch (MessagingException me) {
22196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            // this is expected, so eat it
22296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
22396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
22496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
22596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
22654ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler     * Test a strange case that causes open to proceed without mCapabilities
22754ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler     *  open - fail with "-" error code
22854ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler     *  then check capabilities
22954ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler     */
23054ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler    public void testCheckSettingsCapabilities() throws MessagingException {
23154ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler
23254ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler        MockTransport mockTransport = openAndInjectMockTransport();
23354ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler
23454ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler        // First, preload an open that fails for some reason
23554ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler        mockTransport.expect(null, "-ERR from the Mock Transport.");
23654ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler
23754ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler        // And watch it fail
23854ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler        try {
23954ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler            Pop3Store.Pop3Folder folder = mStore.new Pop3Folder("INBOX");
240244d306ebb0addbc5d87008af9412b76c80e861eMarc Blank            folder.open(OpenMode.READ_WRITE);
24154ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler            fail("Should have thrown exception");
24254ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler        } catch (MessagingException me) {
24354ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler            // Expected - continue.
24454ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler        }
24554ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler
24654ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler        // Now try again (assuming a slightly different connection setup - successful)
24754ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler        // Note, checkSettings is going to try to close the connection again, so we expect
24854ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler        // one extra QUIT before we spin it up again
24954ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler        mockTransport.expect("QUIT", "");
25054ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler        mockTransport.expectClose();
25154ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler        setupOpenFolder(mockTransport, 0, "UIDL");
25254ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler        mockTransport.expect("QUIT", "");
25354ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler        mStore.checkSettings();
25454ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler    }
25554ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler
25654ab7a27a3756a241ba06f0762969cf5a338bf60Andy Stadler    /**
25796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Test small Store & Folder functions that manage folders & namespace
25896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
259e87ff6c3cbbfc5e3636f9827b58820652e3ea1c5Todd Kennedy    public void testStoreFoldersFunctions() {
260a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
26196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // getPersonalNamespaces() always returns INBOX folder
262200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy        Folder[] folders = mStore.updateFolders();
26396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(1, folders.length);
26496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertSame(mFolder, folders[0]);
26596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
26696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // getName() returns the name we were created with.  If "inbox", converts to INBOX
26796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals("INBOX", mFolder.getName());
26896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Pop3Store.Pop3Folder folderMixedCaseInbox = mStore.new Pop3Folder("iNbOx");
26996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals("INBOX", folderMixedCaseInbox.getName());
27096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Pop3Store.Pop3Folder folderNotInbox = mStore.new Pop3Folder("NOT-INBOX");
27196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals("NOT-INBOX", folderNotInbox.getName());
272a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
27396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // exists() true if name is INBOX
27496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertTrue(mFolder.exists());
27596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertTrue(folderMixedCaseInbox.exists());
27696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertFalse(folderNotInbox.exists());
27796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
278a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
27996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
28096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Test small Folder functions that don't really do anything in Pop3
28196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
282a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy    public void testSmallFolderFunctions() {
283a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
2844f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        // getMode() returns OpenMode.READ_WRITE
2854f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        assertEquals(OpenMode.READ_WRITE, mFolder.getMode());
286c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler
287c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler        // canCreate() && create() return false
288c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler        assertFalse(mFolder.canCreate(FolderType.HOLDS_FOLDERS));
289c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler        assertFalse(mFolder.canCreate(FolderType.HOLDS_MESSAGES));
29096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertFalse(mFolder.create(FolderType.HOLDS_FOLDERS));
29196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertFalse(mFolder.create(FolderType.HOLDS_MESSAGES));
292c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler
29396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // getUnreadMessageCount() always returns -1
29496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(-1, mFolder.getUnreadMessageCount());
295a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
29696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // getPermanentFlags() returns { Flag.DELETED }
29796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Flag[] flags = mFolder.getPermanentFlags();
29896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(1, flags.length);
29996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(Flag.DELETED, flags[0]);
300a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
30196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // delete(boolean recurse) does nothing
30296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // TODO - it should!
30396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mFolder.delete(false);
304a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
30596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // expunge() returns null
30696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertNull(mFolder.expunge());
307a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
30896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // copyMessages() is unsupported
30996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        try {
3105551f7feb210313aaf3e5a33cdaec5f991ba3288Andy Stadler            mFolder.copyMessages(null, null, null);
31196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            fail("Exception not thrown by copyMessages()");
31296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        } catch (UnsupportedOperationException e) {
31396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            // expected - succeed
31496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
31596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
316a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
31796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
3181f48259d22001f3e745e34e1bf142dfaf6cad94bAndy Stadler     * Lightweight test to confirm that POP3 hasn't implemented any folder roles yet.
3191f48259d22001f3e745e34e1bf142dfaf6cad94bAndy Stadler     */
320e87ff6c3cbbfc5e3636f9827b58820652e3ea1c5Todd Kennedy    public void testNoFolderRolesYet() {
321200c6bd9fa19b78acc2c1664f858521aa9885353Todd Kennedy        Folder[] remoteFolders = mStore.updateFolders();
3221f48259d22001f3e745e34e1bf142dfaf6cad94bAndy Stadler        for (Folder folder : remoteFolders) {
323a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy            assertEquals(Folder.FolderRole.UNKNOWN, folder.getRole());
3241f48259d22001f3e745e34e1bf142dfaf6cad94bAndy Stadler        }
3251f48259d22001f3e745e34e1bf142dfaf6cad94bAndy Stadler    }
3261f48259d22001f3e745e34e1bf142dfaf6cad94bAndy Stadler
3271f48259d22001f3e745e34e1bf142dfaf6cad94bAndy Stadler    /**
328c9f151d4fe47c5d426109822a7042ae8bbeb0a06Andy Stadler     * Lightweight test to confirm that POP3 is requesting sent-message-upload.
329c9f151d4fe47c5d426109822a7042ae8bbeb0a06Andy Stadler     */
330c9f151d4fe47c5d426109822a7042ae8bbeb0a06Andy Stadler    public void testSentUploadRequested() {
331a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy        assertTrue(mStore.requireCopyMessageToSentFolder());
332c9f151d4fe47c5d426109822a7042ae8bbeb0a06Andy Stadler    }
333c9f151d4fe47c5d426109822a7042ae8bbeb0a06Andy Stadler
334c9f151d4fe47c5d426109822a7042ae8bbeb0a06Andy Stadler    /**
33596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Test the process of opening and indexing a mailbox with one unread message in it.
336a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
33796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * TODO should create an instrumented listener to confirm all expected callbacks.  Then use
33896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * it everywhere we could have passed a message listener.
33996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
34096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void testOneUnread() throws MessagingException {
341a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
34296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        MockTransport mockTransport = openAndInjectMockTransport();
343a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
34496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        checkOneUnread(mockTransport);
34596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
34696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
34796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
3484f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi     * Test the process of opening and getting message by uid.
3494f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi     */
3504f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi    public void testGetMessageByUid() throws MessagingException {
351a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
3524f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        MockTransport mockTransport = openAndInjectMockTransport();
353a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
3544f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        setupOpenFolder(mockTransport, 2, null);
355244d306ebb0addbc5d87008af9412b76c80e861eMarc Blank        mFolder.open(OpenMode.READ_WRITE);
3564f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        // check message count
3574f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        assertEquals(2, mFolder.getMessageCount());
3584f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi
3594f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        // setup 2 messages
3604f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        setupUidlSequence(mockTransport, 2);
3614f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        String uid1 = getSingleMessageUID(1);
3624f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        String uid2 = getSingleMessageUID(2);
3634f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        String uid3 = getSingleMessageUID(3);
364a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
3654f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        Message msg1 = mFolder.getMessage(uid1);
3664f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        assertTrue("message with uid1", msg1 != null);
3674f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi
3684f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        // uid3 does not exist
3694f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        Message msg3 = mFolder.getMessage(uid3);
3704f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        assertTrue("message with uid3", msg3 == null);
3714f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi
3724f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        Message msg2 = mFolder.getMessage(uid2);
3734f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi        assertTrue("message with uid2", msg2 != null);
3744f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi    }
3754f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi
3764f23ebd3dcca596533a33e6faedb446a814d32e3Takaoka G. Tadashi    /**
37796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Test the scenario where the transport is "open" but not really (e.g. server closed).  Two
37896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * things should happen:  We should see an intermediate failure that makes sense, and the next
37996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * operation should reopen properly.
380a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
381092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * There are multiple versions of this test because we are simulating the steps of
38296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * MessagingController.synchronizeMailboxSyncronous() and we will inject the failure a bit
38396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * further along in each case, to test various recovery points.
384a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
385092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * This test confirms that Pop3Store needs to call close() in the IOExceptionHandler in
386092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * Pop3Folder.getMessages(), due to a closure before the UIDL command completes.
38796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
388092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler    public void testCatchClosed1a() throws MessagingException {
389092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
39096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        MockTransport mockTransport = openAndInjectMockTransport();
391092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
39296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        openFolderWithMessage(mockTransport);
393092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
39496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // cause the next sequence to fail on the readLine() calls
39596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mockTransport.closeInputStream();
396092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
39796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // index the message(s) - it should fail, because our stream is broken
39896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        try {
39996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            setupUidlSequence(mockTransport, 1);
40096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            Message[] messages = mFolder.getMessages(1, 1, null);
40196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            assertEquals(1, messages.length);
40296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            assertEquals(getSingleMessageUID(1), messages[0].getUid());
40396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            fail("Broken stream should cause getMessages() to throw.");
404092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        } catch(MessagingException me) {
405092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            // success
40696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
407092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
408092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // At this point the UI would display connection error, which is fine.  Now, the real
409092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // test is, can we recover?  So I'll just repeat the above steps, without the failure.
410092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // NOTE: everything from here down is copied from testOneUnread() and should be consolidated
411092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
412092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // confirm that we're closed at this point
4132720a818d5de169734434b114adfdf824a485f55Marc Blank        assertFalse("folder should be 'closed' after an IOError", mFolder.isOpen());
414092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
415092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // and confirm that the next connection will be OK
416092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        checkOneUnread(mockTransport);
417092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler    }
418092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
419092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler    /**
420092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * Test the scenario where the transport is "open" but not really (e.g. server closed).  Two
421092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * things should happen:  We should see an intermediate failure that makes sense, and the next
422092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * operation should reopen properly.
423a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
424092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * There are multiple versions of this test because we are simulating the steps of
425092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * MessagingController.synchronizeMailboxSyncronous() and we will inject the failure a bit
426092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * further along in each case, to test various recovery points.
427a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
428092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * This test confirms that Pop3Store needs to call close() in the IOExceptionHandler in
429092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * Pop3Folder.getMessages(), due to non-numeric data in a multi-line UIDL.
430092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     */
431092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler    public void testCatchClosed1b() throws MessagingException {
432092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
433092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        MockTransport mockTransport = openAndInjectMockTransport();
434092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
435092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        openFolderWithMessage(mockTransport);
436092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
437092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // index the message(s) - it should fail, because our stream is broken
438092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        try {
439092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            // setupUidlSequence(mockTransport, 1);
440092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            mockTransport.expect("UIDL", "+OK sending UIDL list");
441092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            mockTransport.expect(null, "bad-data" + " " + "THE-UIDL");
442092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            mockTransport.expect(null, ".");
443092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
444092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            Message[] messages = mFolder.getMessages(1, 1, null);
445092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            fail("Bad UIDL should cause getMessages() to throw.");
446092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        } catch(MessagingException me) {
44796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            // success
44896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
449092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
45096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // At this point the UI would display connection error, which is fine.  Now, the real
45196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // test is, can we recover?  So I'll just repeat the above steps, without the failure.
45296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // NOTE: everything from here down is copied from testOneUnread() and should be consolidated
453092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
45496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // confirm that we're closed at this point
4552720a818d5de169734434b114adfdf824a485f55Marc Blank        assertFalse("folder should be 'closed' after an IOError", mFolder.isOpen());
456092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
457092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // and confirm that the next connection will be OK
458092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        checkOneUnread(mockTransport);
459092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler    }
460092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
461092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler    /**
462092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * Test the scenario where the transport is "open" but not really (e.g. server closed).  Two
463092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * things should happen:  We should see an intermediate failure that makes sense, and the next
464092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * operation should reopen properly.
465a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
466092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * There are multiple versions of this test because we are simulating the steps of
467092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * MessagingController.synchronizeMailboxSyncronous() and we will inject the failure a bit
468092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * further along in each case, to test various recovery points.
469a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
470092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * This test confirms that Pop3Store needs to call close() in the IOExceptionHandler in
471092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * Pop3Folder.getMessages(), due to non-numeric data in a single-line UIDL.
472092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     */
473092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler    public void testCatchClosed1c() throws MessagingException {
474092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
475092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        MockTransport mockTransport = openAndInjectMockTransport();
476092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
477092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // openFolderWithMessage(mockTransport);
478092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        setupOpenFolder(mockTransport, 6000, null);
479244d306ebb0addbc5d87008af9412b76c80e861eMarc Blank        mFolder.open(OpenMode.READ_ONLY);
480092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        assertEquals(6000, mFolder.getMessageCount());
481092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
482092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // index the message(s) - it should fail, because our stream is broken
483092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        try {
484092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            // setupUidlSequence(mockTransport, 1);
485092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            mockTransport.expect("UIDL 1", "+OK " + "bad-data" + " " + "THE-UIDL");
486092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
487092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            Message[] messages = mFolder.getMessages(1, 1, null);
488092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            fail("Bad UIDL should cause getMessages() to throw.");
489092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        } catch(MessagingException me) {
490092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            // success
491092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        }
492092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
493092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // At this point the UI would display connection error, which is fine.  Now, the real
494092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // test is, can we recover?  So I'll just repeat the above steps, without the failure.
495092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // NOTE: everything from here down is copied from testOneUnread() and should be consolidated
496092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
497092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // confirm that we're closed at this point
4982720a818d5de169734434b114adfdf824a485f55Marc Blank        assertFalse("folder should be 'closed' after an IOError", mFolder.isOpen());
499092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
50096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // and confirm that the next connection will be OK
50196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        checkOneUnread(mockTransport);
50296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
50396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
50496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
50596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Test the scenario where the transport is "open" but not really (e.g. server closed).  Two
50696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * things should happen:  We should see an intermediate failure that makes sense, and the next
50796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * operation should reopen properly.
508a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
509a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     * There are multiple versions of this test because we are simulating the steps of
51096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * MessagingController.synchronizeMailboxSyncronous() and we will inject the failure a bit
51196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * further along in each case, to test various recovery points.
512a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
513a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     * This test confirms that Pop3Store needs to call close() in the first IOExceptionHandler in
51496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Pop3Folder.fetch(), for a failure in the call to indexUids().
51596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
51696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void testCatchClosed2() throws MessagingException {
517a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
51896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        MockTransport mockTransport = openAndInjectMockTransport();
519a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
52096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        openFolderWithMessage(mockTransport);
521a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
52296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // index the message(s)
52396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        setupUidlSequence(mockTransport, 1);
52496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Message[] messages = mFolder.getMessages(1, 1, null);
52596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(1, messages.length);
526a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy        assertEquals(getSingleMessageUID(1), messages[0].getUid());
527a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
52896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // cause the next sequence to fail on the readLine() calls
52996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mockTransport.closeInputStream();
530a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
53196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        try {
53296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            // try the basic fetch of flags & envelope
53396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            setupListSequence(mockTransport, 1);
53496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            FetchProfile fp = new FetchProfile();
53596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            fp.add(FetchProfile.Item.FLAGS);
53696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            fp.add(FetchProfile.Item.ENVELOPE);
53796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mFolder.fetch(messages, fp, null);
53896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            assertEquals(PER_MESSAGE_SIZE, messages[0].getSize());
53996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            fail("Broken stream should cause fetch() to throw.");
54096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
54196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        catch(MessagingException me) {
54296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            // success
54396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
54496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
54596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // At this point the UI would display connection error, which is fine.  Now, the real
54696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // test is, can we recover?  So I'll just repeat the above steps, without the failure.
54796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // NOTE: everything from here down is copied from testOneUnread() and should be consolidated
548a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
54996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // confirm that we're closed at this point
5502720a818d5de169734434b114adfdf824a485f55Marc Blank        assertFalse("folder should be 'closed' after an IOError", mFolder.isOpen());
551a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
55296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // and confirm that the next connection will be OK
55396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        checkOneUnread(mockTransport);
55496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
555a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
55696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
55796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Test the scenario where the transport is "open" but not really (e.g. server closed).  Two
55896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * things should happen:  We should see an intermediate failure that makes sense, and the next
55996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * operation should reopen properly.
560a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
56196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * There are multiple versions of this test because we have to check additional places where
56296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Pop3Store and/or Pop3Folder should be dealing with IOErrors.
563a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
564a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     * This test confirms that Pop3Store needs to call close() in the first IOExceptionHandler in
56596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Pop3Folder.fetch(), for a failure in the call to fetchEnvelope().
56696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
567092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler    public void testCatchClosed2a() throws MessagingException {
568a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
569092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        MockTransport mockTransport = openAndInjectMockTransport();
570a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
571092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        openFolderWithMessage(mockTransport);
572a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
573092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // index the message(s)
574092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        setupUidlSequence(mockTransport, 1);
575092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        Message[] messages = mFolder.getMessages(1, 1, null);
576092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        assertEquals(1, messages.length);
577a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy        assertEquals(getSingleMessageUID(1), messages[0].getUid());
578092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
579092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // try the basic fetch of flags & envelope, but the LIST command fails
580092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        setupBrokenListSequence(mockTransport, 1);
581092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        try {
582092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            FetchProfile fp = new FetchProfile();
583092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            fp.add(FetchProfile.Item.FLAGS);
584092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            fp.add(FetchProfile.Item.ENVELOPE);
585092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            mFolder.fetch(messages, fp, null);
586092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            assertEquals(PER_MESSAGE_SIZE, messages[0].getSize());
587092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            fail("Broken stream should cause fetch() to throw.");
588092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        } catch(MessagingException me) {
589092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            // success
590092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        }
591092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
592092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // At this point the UI would display connection error, which is fine.  Now, the real
593092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // test is, can we recover?  So I'll just repeat the above steps, without the failure.
594092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // NOTE: everything from here down is copied from testOneUnread() and should be consolidated
595a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
596092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // confirm that we're closed at this point
5972720a818d5de169734434b114adfdf824a485f55Marc Blank        assertFalse("folder should be 'closed' after an IOError", mFolder.isOpen());
598a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
599092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // and confirm that the next connection will be OK
600092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        checkOneUnread(mockTransport);
60196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
602a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
60396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
60496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Test the scenario where the transport is "open" but not really (e.g. server closed).  Two
60596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * things should happen:  We should see an intermediate failure that makes sense, and the next
60696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * operation should reopen properly.
607a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
608a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     * There are multiple versions of this test because we are simulating the steps of
60996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * MessagingController.synchronizeMailboxSyncronous() and we will inject the failure a bit
61096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * further along in each case, to test various recovery points.
611a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
612a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     * This test confirms that Pop3Store needs to call close() in the second IOExceptionHandler in
61396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Pop3Folder.fetch().
61496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
61596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void testCatchClosed3() throws MessagingException {
616a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
61796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        MockTransport mockTransport = openAndInjectMockTransport();
618a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
61996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        openFolderWithMessage(mockTransport);
620a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
62196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // index the message(s)
62296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        setupUidlSequence(mockTransport, 1);
62396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Message[] messages = mFolder.getMessages(1, 1, null);
62496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(1, messages.length);
625a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy        assertEquals(getSingleMessageUID(1), messages[0].getUid());
62696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
62796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // try the basic fetch of flags & envelope
62896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        setupListSequence(mockTransport, 1);
62996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        FetchProfile fp = new FetchProfile();
63096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        fp.add(FetchProfile.Item.FLAGS);
63196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        fp.add(FetchProfile.Item.ENVELOPE);
63296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mFolder.fetch(messages, fp, null);
63396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(PER_MESSAGE_SIZE, messages[0].getSize());
63496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
63596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // cause the next sequence to fail on the readLine() calls
63696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mockTransport.closeInputStream();
63796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
63896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        try {
63996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            // now try fetching the message
64096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            setupSingleMessage(mockTransport, 1, false);
64196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            fp = new FetchProfile();
64296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            fp.add(FetchProfile.Item.BODY);
64396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mFolder.fetch(messages, fp, null);
64496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            checkFetchedMessage(messages[0], 1, false);
64596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            fail("Broken stream should cause fetch() to throw.");
64696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
64796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        catch(MessagingException me) {
64896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            // success
64996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
65096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
65196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // At this point the UI would display connection error, which is fine.  Now, the real
65296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // test is, can we recover?  So I'll just repeat the above steps, without the failure.
65396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // NOTE: everything from here down is copied from testOneUnread() and should be consolidated
654a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
65596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // confirm that we're closed at this point
6562720a818d5de169734434b114adfdf824a485f55Marc Blank        assertFalse("folder should be 'closed' after an IOError", mFolder.isOpen());
657a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
65896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // and confirm that the next connection will be OK
65996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        checkOneUnread(mockTransport);
66096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
661a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
66296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
66396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Test the scenario where the transport is "open" but not really (e.g. server closed).  Two
66496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * things should happen:  We should see an intermediate failure that makes sense, and the next
66596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * operation should reopen properly.
666a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
66796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * There are multiple versions of this test because we have to check additional places where
66896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Pop3Store and/or Pop3Folder should be dealing with IOErrors.
669a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
670a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     * This test confirms that Pop3Store needs to call close() in the IOExceptionHandler in
67196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Pop3Folder.setFlags().
67296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
67396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void testCatchClosed4() throws MessagingException {
674a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
67596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        MockTransport mockTransport = openAndInjectMockTransport();
676a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
67796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        openFolderWithMessage(mockTransport);
678a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
67996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // index the message(s)
68096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        setupUidlSequence(mockTransport, 1);
68196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Message[] messages = mFolder.getMessages(1, 1, null);
68296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(1, messages.length);
68396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(getSingleMessageUID(1), messages[0].getUid());
684a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
68596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // cause the next sequence to fail on the readLine() calls
68696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mockTransport.closeInputStream();
68796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
68896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // delete 'em all - should fail because of broken stream
68996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        try {
69096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mockTransport.expect("DELE 1", "+OK message deleted");
69196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mFolder.setFlags(messages, new Flag[] { Flag.DELETED }, true);
69296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            fail("Broken stream should cause fetch() to throw.");
69396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
69496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        catch(MessagingException me) {
69596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            // success
69696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
69796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
69896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // At this point the UI would display connection error, which is fine.  Now, the real
69996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // test is, can we recover?  So I'll just repeat the above steps, without the failure.
70096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // NOTE: everything from here down is copied from testOneUnread() and should be consolidated
701a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
70296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // confirm that we're closed at this point
7032720a818d5de169734434b114adfdf824a485f55Marc Blank        assertFalse("folder should be 'closed' after an IOError", mFolder.isOpen());
704a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
70596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // and confirm that the next connection will be OK
70696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        checkOneUnread(mockTransport);
70796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
708a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
70996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
71096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Test the scenario where the transport is "open" but not really (e.g. server closed).  Two
71196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * things should happen:  We should see an intermediate failure that makes sense, and the next
71296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * operation should reopen properly.
713a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
71496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * There are multiple versions of this test because we have to check additional places where
71596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Pop3Store and/or Pop3Folder should be dealing with IOErrors.
716a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
717a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     * This test confirms that Pop3Store needs to call close() in the first IOExceptionHandler in
71896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Pop3Folder.open().
71996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
72096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void testCatchClosed5() {
72196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // TODO cannot write this test until we can inject stream closures mid-sequence
72296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
723a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
72496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
72596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Test the scenario where the transport is "open" but not really (e.g. server closed).  Two
72696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * things should happen:  We should see an intermediate failure that makes sense, and the next
72796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * operation should reopen properly.
728a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
72996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * There are multiple versions of this test because we have to check additional places where
73096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Pop3Store and/or Pop3Folder should be dealing with IOErrors.
731a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
732a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     * This test confirms that Pop3Store needs to call close() in the second IOExceptionHandler in
733092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * Pop3Folder.open() (when it calls STAT and the response is empty of garbagey).
73496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
735092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler    public void testCatchClosed6a() throws MessagingException {
736a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
737092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        MockTransport mockTransport = openAndInjectMockTransport();
738a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
739092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // like openFolderWithMessage(mockTransport) but with a broken STAT report (empty response)
740092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        setupOpenFolder(mockTransport, -1, null);
741092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        try {
742244d306ebb0addbc5d87008af9412b76c80e861eMarc Blank            mFolder.open(OpenMode.READ_ONLY);
743092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            fail("Broken STAT should cause open() to throw.");
744092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        } catch(MessagingException me) {
745092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            // success
746092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        }
747a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
748092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // At this point the UI would display connection error, which is fine.  Now, the real
749092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // test is, can we recover?  So I'll try a new connection, without the failure.
750a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
751092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // confirm that we're closed at this point
7522720a818d5de169734434b114adfdf824a485f55Marc Blank        assertFalse("folder should be 'closed' after an IOError", mFolder.isOpen());
753a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
754092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        // and confirm that the next connection will be OK
755092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        checkOneUnread(mockTransport);
756092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler    }
757a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
758092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler    /**
759092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * Test the scenario where the transport is "open" but not really (e.g. server closed).  Two
760092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * things should happen:  We should see an intermediate failure that makes sense, and the next
761092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * operation should reopen properly.
762a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
763092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * There are multiple versions of this test because we have to check additional places where
764092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * Pop3Store and/or Pop3Folder should be dealing with IOErrors.
765a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
766a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     * This test confirms that Pop3Store needs to call close() in the second IOExceptionHandler in
767092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * Pop3Folder.open() (when it calls STAT, and there is no response at all).
768092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     */
769a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy    public void testCatchClosed6b() {
77096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // TODO cannot write this test until we can inject stream closures mid-sequence
77196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
772a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
77396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
774a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     * Given an initialized mock transport, open it and attempt to "read" one unread message from
77596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * it.  This can be used as a basic test of functionality and it should be possible to call this
77696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * repeatedly (if you close the folder between calls).
777a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
77896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param mockTransport the mock transport we're using
77996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
78096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private void checkOneUnread(MockTransport mockTransport) throws MessagingException {
78196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        openFolderWithMessage(mockTransport);
782a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
78396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // index the message(s)
78496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        setupUidlSequence(mockTransport, 1);
78596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Message[] messages = mFolder.getMessages(1, 1, null);
78696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(1, messages.length);
78796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(getSingleMessageUID(1), messages[0].getUid());
788a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
78996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // try the basic fetch of flags & envelope
79096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        setupListSequence(mockTransport, 1);
79196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        FetchProfile fp = new FetchProfile();
79296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        fp.add(FetchProfile.Item.FLAGS);
79396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        fp.add(FetchProfile.Item.ENVELOPE);
79496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mFolder.fetch(messages, fp, null);
79596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(PER_MESSAGE_SIZE, messages[0].getSize());
796a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
797a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy        // A side effect of how messages work is that if you get fields that are empty,
7983469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        // then empty arrays are written back into the parsed header fields (e.g. mTo, mFrom).  The
7993469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        // standard message parser needs to clear these before parsing.  Make sure that this
8003469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        // is happening.  (This doesn't affect IMAP, which reads the headers directly via
8013469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        // IMAP evelopes.)
8023469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        MimeMessage message = (MimeMessage) messages[0];
8033469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        message.getRecipients(RecipientType.TO);
8043469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        message.getRecipients(RecipientType.CC);
8053469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        message.getRecipients(RecipientType.BCC);
80696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
80796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // now try fetching the message
80896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        setupSingleMessage(mockTransport, 1, false);
80996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        fp = new FetchProfile();
81096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        fp.add(FetchProfile.Item.BODY);
81196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mFolder.fetch(messages, fp, null);
81296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        checkFetchedMessage(messages[0], 1, false);
81396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
814645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler
815645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler    /**
816645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler     * A group of tests to confirm that we're properly juggling the RETR and TOP commands.
817645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler     * Some servers (hello, live.com) support TOP but don't support CAPA.  So we ignore CAPA
818645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler     * and just try TOP.
819645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler     */
820645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler    public void testRetrVariants() throws MessagingException {
821645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        MockTransport mockTransport = openAndInjectMockTransport();
822645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        openFolderWithMessage(mockTransport);
823645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler
824645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        // index the message(s)
825645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        setupUidlSequence(mockTransport, 2);
826645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        Message[] messages = mFolder.getMessages(1, 2, null);
827645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        assertEquals(2, messages.length);
828645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler
829645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        // basic fetch of flags & envelope
830645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        setupListSequence(mockTransport, 2);
831645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        FetchProfile fp = new FetchProfile();
832645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        fp.add(FetchProfile.Item.FLAGS);
833645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        fp.add(FetchProfile.Item.ENVELOPE);
834645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        mFolder.fetch(messages, fp, null);
835645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler
836a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy        // A side effect of how messages work is that if you get fields that are empty,
837645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        // then empty arrays are written back into the parsed header fields (e.g. mTo, mFrom).  The
838645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        // standard message parser needs to clear these before parsing.  Make sure that this
839645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        // is happening.  (This doesn't affect IMAP, which reads the headers directly via
840645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        // IMAP envelopes.)
841645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        for (Message message : messages) {
842645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler            message.getRecipients(RecipientType.TO);
843645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler            message.getRecipients(RecipientType.CC);
844645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler            message.getRecipients(RecipientType.BCC);
845645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        }
846645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler
847645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        // In the cases below, we fetch BODY_SANE which tries to load the first chunk of the
848645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        // message (not the entire thing) in order to quickly access the headers.
849645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        // In the first test, TOP succeeds
850645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        Message[] singleMessage = new Message[] { messages[0] };
851645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        setupSingleMessageTop(mockTransport, 1, true, true);        // try TOP & succeed
852645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        fp = new FetchProfile();
853645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        fp.add(FetchProfile.Item.BODY_SANE);
854645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        mFolder.fetch(singleMessage, fp, null);
855645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        checkFetchedMessage(singleMessage[0], 1, false);
856645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler
857645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        // In the 2nd test, TOP fails, so we should fall back to RETR
858645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        singleMessage[0] = messages[1];
859645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        setupSingleMessageTop(mockTransport, 2, true, false);        // try TOP & fail
860645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        fp = new FetchProfile();
861645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        fp.add(FetchProfile.Item.BODY_SANE);
862645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        mFolder.fetch(singleMessage, fp, null);
863645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        checkFetchedMessage(singleMessage[0], 2, false);
864645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler    }
865645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler
86696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
86796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Set up a basic MockTransport. open it, and inject it into mStore
86896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
86996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private MockTransport openAndInjectMockTransport() {
87096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // Create mock transport and inject it into the POP3Store that's already set up
87117d3a29c9d8f7a27c463239f190bdcc4e0804527Jerry Xie        MockTransport mockTransport = new MockTransport(mContext, mHostAuth);
87217d3a29c9d8f7a27c463239f190bdcc4e0804527Jerry Xie        mockTransport.setSecurity(HostAuth.FLAG_NONE, false);
87396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mStore.setTransport(mockTransport);
87496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return mockTransport;
87596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
876a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
87796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
87896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Open a folder that's preloaded with one unread message.
879a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
88096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param mockTransport the mock transport we're using
88196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
88296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private void openFolderWithMessage(MockTransport mockTransport) throws MessagingException {
88396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // try to open it
88496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        setupOpenFolder(mockTransport, 1, null);
885244d306ebb0addbc5d87008af9412b76c80e861eMarc Blank        mFolder.open(OpenMode.READ_ONLY);
886a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
88796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // check message count
88896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(1, mFolder.getMessageCount());
88996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
890a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
89196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
89296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Look at a fetched message and confirm that it is complete.
893a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
89496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * TODO this needs to be more dynamic, not just hardcoded for empty message #1.
895a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
89696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param message the fetched message to be checked
89796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param msgNum the message number
89896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
899a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy    private void checkFetchedMessage(Message message, int msgNum, boolean body)
90096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            throws MessagingException {
90196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // check To:
90296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Address[] to = message.getRecipients(RecipientType.TO);
90396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertNotNull(to);
90496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(1, to.length);
90596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals("Smith@Registry.Org", to[0].getAddress());
90696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertNull(to[0].getPersonal());
907a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
90896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // check From:
90996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Address[] from = message.getFrom();
91096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertNotNull(from);
91196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals(1, from.length);
91296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertEquals("Jones@Registry.Org", from[0].getAddress());
91396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        assertNull(from[0].getPersonal());
914a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
9153469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        // check Cc:
9163469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        Address[] cc = message.getRecipients(RecipientType.CC);
9173469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        assertNotNull(cc);
9183469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        assertEquals(1, cc.length);
9193469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        assertEquals("Chris@Registry.Org", cc[0].getAddress());
9203469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        assertNull(cc[0].getPersonal());
9213469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project
9223469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        // check Reply-To:
9233469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        Address[] replyto = message.getReplyTo();
9243469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        assertNotNull(replyto);
9253469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        assertEquals(1, replyto.length);
9263469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        assertEquals("Roger@Registry.Org", replyto[0].getAddress());
9273469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        assertNull(replyto[0].getPersonal());
92896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
92996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // TODO date
930a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy
93196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // TODO check body (if applicable)
93296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
933092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
93496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
93596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Helper which stuffs the mock with enough strings to satisfy a call to Pop3Folder.open()
936a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
93796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param mockTransport the mock transport we're using
938092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * @param statCount the number of messages to indicate in the STAT, or -1 for broken STAT
93996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param capabilities if non-null, comma-separated list of capabilities
94096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
94196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private void setupOpenFolder(MockTransport mockTransport, int statCount, String capabilities) {
94296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mockTransport.expect(null, "+OK Hello there from the Mock Transport.");
94396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (capabilities == null) {
94496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mockTransport.expect("CAPA", "-ERR unimplemented");
94596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        } else {
94696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mockTransport.expect("CAPA", "+OK capabilities follow");
94796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mockTransport.expect(null, capabilities.split(","));        // one capability per line
94896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mockTransport.expect(null, ".");                            // terminated by "."
94996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
95096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mockTransport.expect("USER user", "+OK User name accepted");
95196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mockTransport.expect("PASS password", "+OK Logged in");
952092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        if (statCount == -1) {
953092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            mockTransport.expect("STAT", "");
954092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        } else {
955092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            String stat = "+OK " + Integer.toString(statCount) + " "
956092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler                    + Integer.toString(PER_MESSAGE_SIZE * statCount);
957092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            mockTransport.expect("STAT", stat);
958092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        }
95996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
960092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
96196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
96296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Setup expects for a UIDL on a mailbox with 0 or more messages in it.
96396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param transport The mock transport to preload
96496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param numMessages The number of messages to return from UIDL.
96596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
96696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private static void setupUidlSequence(MockTransport transport, int numMessages) {
967a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy        transport.expect("UIDL", "+OK sending UIDL list");
96896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        for (int msgNum = 1; msgNum <= numMessages; ++msgNum) {
96996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            transport.expect(null, Integer.toString(msgNum) + " " + getSingleMessageUID(msgNum));
97096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
97196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        transport.expect(null, ".");
97296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
973092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
97496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
97596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Setup expects for a LIST on a mailbox with 0 or more messages in it.
97696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param transport The mock transport to preload
97796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param numMessages The number of messages to return from LIST.
97896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
97996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private static void setupListSequence(MockTransport transport, int numMessages) {
980a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy        transport.expect("LIST", "+OK sending scan listing");
98196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        for (int msgNum = 1; msgNum <= numMessages; ++msgNum) {
982a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy            transport.expect(null, Integer.toString(msgNum) + " " +
98396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                    Integer.toString(PER_MESSAGE_SIZE * msgNum));
98496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
98596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        transport.expect(null, ".");
98696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
987092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
988092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler    /**
989092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * Setup expects for a LIST on a mailbox with 0 or more messages in it, except that
990092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * this time the pipe fails, and we return empty lines.
991092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * @param transport The mock transport to preload
992092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     * @param numMessages The number of messages to return from LIST.
993092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler     */
994092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler    private static void setupBrokenListSequence(MockTransport transport, int numMessages) {
995092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        transport.expect("LIST", "");
996092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        for (int msgNum = 1; msgNum <= numMessages; ++msgNum) {
997092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler            transport.expect(null, "");
998092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        }
999092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler        transport.expect(null, "");
1000092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler    }
1001092d35c98d00c5a8b1ba93f51f8e59220f1488cbAndrew Stadler
100296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
100396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Setup a single message to be retrieved.
1004a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
100596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Per RFC822 here is a minimal message header:
100696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *     Date:     26 Aug 76 1429 EDT
100796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *     From:     Jones@Registry.Org
100896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *     To:       Smith@Registry.Org
1009a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
10103469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project     * We'll add the following fields to support additional tests:
10113469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project     *     Cc:       Chris@Registry.Org
10123469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project     *     Reply-To: Roger@Registry.Org
1013a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy     *
101496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param transport the mock transport to preload
101596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param msgNum the message number to expect and return
101696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param body if true, a non-empty body will be added
101796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
101896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private static void setupSingleMessage(MockTransport transport, int msgNum, boolean body) {
1019645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        setupSingleMessageTop(transport, msgNum, false, false);
1020645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler    }
1021645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler
1022645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler    /**
1023645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler     * Setup a single message to be retrieved (headers only).
1024645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler     * This is very similar to setupSingleMessage() but is intended to test the BODY_SANE
1025645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler     * fetch mode.
1026645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler     * @param transport the mock transport
1027645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler     * @param msgNum the message number to expect and return
1028645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler     * @param topTry if true, the "client" is going to attempt the TOP command
1029645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler     * @param topSupported if true, the "server" supports the TOP command
1030645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler     */
1031645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler    private static void setupSingleMessageTop(MockTransport transport, int msgNum,
1032645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler            boolean topTry, boolean topSupported) {
1033645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        String msgNumString = Integer.toString(msgNum);
1034645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        String topCommand = "TOP " + msgNumString + " 673";
1035645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        String retrCommand = "RETR " + msgNumString;
1036645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler
1037645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        if (topTry) {
1038645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler            if (topSupported) {
1039645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler                transport.expect(topCommand, "+OK message follows");
1040645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler            } else {
1041645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler                transport.expect(topCommand, "-ERR unsupported command");
1042645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler                transport.expect(retrCommand, "+OK message follows");
1043645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler            }
1044645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        } else {
1045645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler            transport.expect(retrCommand, "+OK message follows");
1046645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler        }
1047645fc2830118e19e604f24ba7ffe71c775631f64Andrew Stadler
104896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        transport.expect(null, "Date: 26 Aug 76 1429 EDT");
104996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        transport.expect(null, "From: Jones@Registry.Org");
105096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        transport.expect(null, "To:   Smith@Registry.Org");
10513469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        transport.expect(null, "CC:   Chris@Registry.Org");
10523469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project        transport.expect(null, "Reply-To: Roger@Registry.Org");
105396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        transport.expect(null, "");
105496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        transport.expect(null, ".");
105596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
105696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
105796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
105896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Generates a simple unique code for each message.  Repeatable.
105996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param msgNum The message number
106096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @return a string that can be used as the UID
106196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
106296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private static String getSingleMessageUID(int msgNum) {
106396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        final String UID_HEAD = "ABCDEF-";
106496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        final String UID_TAIL = "";
106596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return UID_HEAD + Integer.toString(msgNum) + UID_TAIL;
106696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
106796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project}
1068