MockTransport.java revision cb95fbe13554ee6b4e46d9fd3bcd983e09a688cb
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.transport;
1896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
1996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport com.android.email.mail.Transport;
2096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
2196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport android.util.Log;
2296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
2396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.io.IOException;
2496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.io.InputStream;
2596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.io.OutputStream;
2696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.net.URI;
2796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.util.ArrayList;
2896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.util.Arrays;
2996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
3096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/**
3196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * This is a mock Transport that is used to test protocols that use MailTransport.
3296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */
3396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectpublic class MockTransport implements Transport {
3496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
3596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    // All flags defining debug or development code settings must be FALSE
3696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    // when code is checked in or released.
3796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private static boolean DEBUG_LOG_STREAMS = true;
3896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
3996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private static String LOG_TAG = "MockTransport";
4096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
4196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private boolean mSslAllowed = false;
4296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private boolean mTlsAllowed = false;
4396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
4496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private boolean mOpen;
4596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private boolean mInputOpen;
4696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private int mConnectionSecurity;
47e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler    private boolean mTrustCertificates;
48cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler    private String mHost;
4996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
5096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private ArrayList<String> mQueuedInput = new ArrayList<String>();
5196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
5296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private static class Transaction {
5396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        public static final int ACTION_INJECT_TEXT = 0;
5496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        public static final int ACTION_SERVER_CLOSE = 1;
5596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        public static final int ACTION_CLIENT_CLOSE = 2;
5696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
5796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        int mAction;
5896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        String mPattern;
5996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        String[] mResponses;
6096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
6196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Transaction(String pattern, String[] responses) {
6296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mAction = ACTION_INJECT_TEXT;
6396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mPattern = pattern;
6496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mResponses = responses;
6596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
6696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
6796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Transaction(int otherType) {
6896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mAction = otherType;
6996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mPattern = null;
7096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mResponses = null;
7196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
7296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
7396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        @Override
7496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        public String toString() {
7596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            switch (mAction) {
7696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                case ACTION_INJECT_TEXT:
7796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                    return mPattern + ": " + Arrays.toString(mResponses);
7896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                case ACTION_SERVER_CLOSE:
7996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                    return "Close the server connection";
8096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                case ACTION_CLIENT_CLOSE:
8196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                    return "Expect the client to close";
8296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                default:
8396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                    return "(Hmm.  Unknown action.)";
8496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            }
8596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
8696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
8796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
8896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private ArrayList<Transaction> mPairs = new ArrayList<Transaction>();
89c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
90c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    /**
91c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler     * Give the mock a pattern to wait for.  No response will be sent.
92c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler     * @param pattern Java RegEx to wait for
93c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler     */
94c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    public void expect(String pattern) {
95c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        expect(pattern, (String[])null);
96c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    }
97c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
9896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
9996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Give the mock a pattern to wait for and a response to send back.
10096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param pattern Java RegEx to wait for
10196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param response String to reply with, or null to acccept string but not respond to it
10296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
10396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void expect(String pattern, String response) {
10496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        expect(pattern, (response == null) ? null : new String[] { response });
10596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
10696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
10796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
10896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Give the mock a pattern to wait for and a multi-line response to send back.
10996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param pattern Java RegEx to wait for
11096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param responses Strings to reply with
11196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
11296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void expect(String pattern, String[] responses) {
11396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Transaction pair = new Transaction(pattern, responses);
11496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mPairs.add(pair);
11596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
11696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
11796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
11896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Tell the Mock Transport that we expect it to be closed.  This will preserve
11996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * the remaining entries in the expect() stream and allow us to "ride over" the close (which
12096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * would normally reset everything).
12196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
12296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void expectClose() {
12396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mPairs.add(new Transaction(Transaction.ACTION_CLIENT_CLOSE));
12496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
12596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
12696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private void sendResponse(String[] responses) {
12796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        for (String s : responses) {
12896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mQueuedInput.add(s);
12996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
13096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
13196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
13296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public boolean canTrySslSecurity() {
133e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler        return (mConnectionSecurity == CONNECTION_SECURITY_SSL);
13496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
13596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
13696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public boolean canTryTlsSecurity() {
137e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler        return (mConnectionSecurity == Transport.CONNECTION_SECURITY_TLS);
13896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
139e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler
140e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler    public boolean canTrustAllCertificates() {
141e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler        return mTrustCertificates;
142e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler    }
143e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler
14496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
14596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * This simulates a condition where the server has closed its side, causing
14696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * reads to fail.
14796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
14896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void closeInputStream() {
14996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mInputOpen = false;
15096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
15196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
15296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void close() {
15396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mOpen = false;
15496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mInputOpen = false;
15596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // unless it was expected as part of a test, reset the stream
15696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (mPairs.size() > 0) {
15796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            Transaction expect = mPairs.remove(0);
15896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            if (expect.mAction == Transaction.ACTION_CLIENT_CLOSE) {
15996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                return;
16096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            }
16196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
16296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mQueuedInput.clear();
16396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mPairs.clear();
16496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
16596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
166cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler    /**
167cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler     * This is a test function (not part of the interface) and is used to set up a result
168cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler     * value for getHost(), if needed for the test.
169cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler     */
170cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler    public void setMockHost(String host) {
171cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler        mHost = host;
172cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler    }
173cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler
17496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public String getHost() {
175cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler        return mHost;
17696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
17796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
17896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public InputStream getInputStream() {
17996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        SmtpSenderUnitTests.assertTrue(mOpen);
18096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return new MockInputStream();
18196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
18296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
18396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
18496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * This normally serves as a pseudo-clone, for use by Imap.  For the purposes of unit testing,
18596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * until we need something more complex, we'll just return the actual MockTransport.  Then we
18696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * don't have to worry about dealing with test metadata like the expects list or socket state.
18796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
18896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public Transport newInstanceWithConfiguration() {
18996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project         return this;
19096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
19196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
19296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public OutputStream getOutputStream() {
19396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        SmtpSenderUnitTests.assertTrue(mOpen);
19496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return new MockOutputStream();
19596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
19696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
19796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public int getPort() {
19896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        SmtpSenderUnitTests.fail("getPort() not implemented");
19996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return 0;
20096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
20196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
20296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public int getSecurity() {
20396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return mConnectionSecurity;
20496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
20596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
20696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public String[] getUserInfoParts() {
20796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        SmtpSenderUnitTests.fail("getUserInfoParts() not implemented");
20896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return null;
20996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
21096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
21196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public boolean isOpen() {
21296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return mOpen;
21396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
21496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
21596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void open() /* throws MessagingException, CertificateValidationException */ {
21696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mOpen = true;
21796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mInputOpen = true;
21896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
21996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
22096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
22196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * This returns one string (if available) to the caller.  Usually this simply pulls strings
22296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * from the mQueuedInput list, but if the list is empty, we also peek the expect list.  This
22396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * supports banners, multi-line responses, and any other cases where we respond without
22496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * a specific expect pattern.
22596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *
22696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * If no response text is available, we assert (failing our test) as an underflow.
22796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *
22896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Logs the read text if DEBUG_LOG_STREAMS is true.
22996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
23096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public String readLine() throws IOException {
23196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        SmtpSenderUnitTests.assertTrue(mOpen);
23296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (!mInputOpen) {
23396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            throw new IOException("Reading from MockTransport with closed input");
23496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
23596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // if there's nothing to read, see if we can find a null-pattern response
23696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (0 == mQueuedInput.size()) {
23796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            Transaction pair = mPairs.get(0);
23896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            if (pair != null && pair.mPattern == null) {
23996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                mPairs.remove(0);
24096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                sendResponse(pair.mResponses);
24196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            }
24296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
24396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        SmtpSenderUnitTests.assertTrue("Underflow reading from MockTransport", 0 != mQueuedInput.size());
24496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        String line = mQueuedInput.remove(0);
24596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (DEBUG_LOG_STREAMS) {
24696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            Log.d(LOG_TAG, "<<< " + line);
24796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
24896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return line;
24996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
25096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
25196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void reopenTls() /* throws MessagingException */ {
25296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        SmtpSenderUnitTests.assertTrue(mOpen);
25396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        SmtpSenderUnitTests.assertTrue(mTlsAllowed);
25496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        SmtpSenderUnitTests.fail("reopenTls() not implemented");
25596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
25696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
257e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler    public void setSecurity(int connectionSecurity, boolean trustAllCertificates) {
25896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mConnectionSecurity = connectionSecurity;
259e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler        mTrustCertificates = trustAllCertificates;
26096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
26196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
26296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void setSoTimeout(int timeoutMilliseconds) /* throws SocketException */ {
26396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
26496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
26596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void setUri(URI uri, int defaultPort) {
26696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        SmtpSenderUnitTests.assertTrue("Don't call setUri on a mock transport", false);
26796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
26896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
26996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
27096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Accepts a single string (command or text) that was written by the code under test.
27196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Because we are essentially mocking a server, we check to see if this string was expected.
27296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * If the string was expected, we push the corresponding responses into the mQueuedInput
27396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * list, for subsequent calls to readLine().  If the string does not match, we assert
27496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * the mismatch.  If no string was expected, we assert it as an overflow.
27596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *
27696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Logs the written text if DEBUG_LOG_STREAMS is true.
27796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
27896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    public void writeLine(String s, String sensitiveReplacement) /* throws IOException */ {
27996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (DEBUG_LOG_STREAMS) {
28096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            Log.d(LOG_TAG, ">>> " + s);
28196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
28296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        SmtpSenderUnitTests.assertTrue(mOpen);
28396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        SmtpSenderUnitTests.assertTrue("Overflow writing to MockTransport", 0 != mPairs.size());
28496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        Transaction pair = mPairs.remove(0);
28596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        SmtpSenderUnitTests.assertTrue("Unexpected string written to MockTransport",
28696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                pair.mPattern != null && s.matches(pair.mPattern));
28796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (pair.mResponses != null) {
28896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            sendResponse(pair.mResponses);
28996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
29096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
29196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
29296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
29396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * This is an InputStream that satisfies the needs of getInputStream()
29496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
29596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private class MockInputStream extends InputStream {
29696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
29796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        byte[] mNextLine = null;
29896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        int mNextIndex = 0;
29996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
30096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        /**
30196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project         * Reads from the same input buffer as readLine()
30296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project         */
30396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        @Override
30496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        public int read() throws IOException {
30596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            if (!mInputOpen) {
30696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                throw new IOException();
30796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            }
30896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
30996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            if (mNextLine != null && mNextIndex < mNextLine.length) {
31096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                return mNextLine[mNextIndex++];
31196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            }
31296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
31396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            // previous line was exhausted so try to get another one
31496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            String next = readLine();
31596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            if (next == null) {
31696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                throw new IOException("Reading from MockTransport with closed input");
31796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            }
31896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mNextLine = (next + "\r\n").getBytes();
31996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mNextIndex = 0;
32096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
32196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            if (mNextLine != null && mNextIndex < mNextLine.length) {
32296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                return mNextLine[mNextIndex++];
32396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            }
32496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
32596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            // no joy - throw an exception
32696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            throw new IOException();
32796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
32896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
32996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
33096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
33196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * This is an OutputStream that satisfies the needs of getOutputStream()
33296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
33396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private class MockOutputStream extends OutputStream {
33496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
33596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        StringBuilder sb = new StringBuilder();
33696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
33796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        @Override
338c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        public void write(int oneByte) {
339c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler            // CR or CRLF will immediately dump previous line (w/o CRLF)
340c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler            if (oneByte == '\r') {
341c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler                writeLine(sb.toString(), null);
342c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler                sb = new StringBuilder();
343c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler            } else if (oneByte == '\n') {
344c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler                // swallow it
345c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler            } else {
34696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                sb.append((char)oneByte);
34796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            }
34896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
34996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
35096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project}