MockTransport.java revision 1a791e675ba5092569125bf09a9fcc721bd4c5e1
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; 26be2ef97220619a3acf6c3dd4eb4b8add26ff452aAndy Stadlerimport java.net.InetAddress; 2796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.net.URI; 2896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.util.ArrayList; 2996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.util.Arrays; 30af6724527e564d35dd27ac35e24dbced554792e5Makoto Onukiimport java.util.regex.Pattern; 31af6724527e564d35dd27ac35e24dbced554792e5Makoto Onuki 32af6724527e564d35dd27ac35e24dbced554792e5Makoto Onukiimport junit.framework.Assert; 3396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 3496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/** 3596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * This is a mock Transport that is used to test protocols that use MailTransport. 3696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 3796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectpublic class MockTransport implements Transport { 3896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 3996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // All flags defining debug or development code settings must be FALSE 4096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // when code is checked in or released. 4196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private static boolean DEBUG_LOG_STREAMS = true; 42a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 4396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private static String LOG_TAG = "MockTransport"; 4496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 45f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki private static final String SPECIAL_RESPONSE_IOEXCEPTION = "!!!IOEXCEPTION!!!"; 46f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki 471a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler private boolean mTlsStarted = false; 48a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 4996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private boolean mOpen; 5096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private boolean mInputOpen; 5196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private int mConnectionSecurity; 52e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler private boolean mTrustCertificates; 53cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler private String mHost; 54be2ef97220619a3acf6c3dd4eb4b8add26ff452aAndy Stadler private InetAddress mLocalAddress; 55be2ef97220619a3acf6c3dd4eb4b8add26ff452aAndy Stadler 5696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private ArrayList<String> mQueuedInput = new ArrayList<String>(); 57be2ef97220619a3acf6c3dd4eb4b8add26ff452aAndy Stadler 5896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private static class Transaction { 5996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public static final int ACTION_INJECT_TEXT = 0; 60f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki public static final int ACTION_CLIENT_CLOSE = 1; 61f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki public static final int ACTION_IO_EXCEPTION = 2; 621a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler public static final int ACTION_START_TLS = 3; 63a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 6496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project int mAction; 6596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String mPattern; 6696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String[] mResponses; 67a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 6896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Transaction(String pattern, String[] responses) { 6996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mAction = ACTION_INJECT_TEXT; 7096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mPattern = pattern; 7196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mResponses = responses; 7296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 73a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 7496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Transaction(int otherType) { 7596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mAction = otherType; 7696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mPattern = null; 7796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mResponses = null; 7896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 79a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 8096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project @Override 8196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public String toString() { 8296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project switch (mAction) { 8396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project case ACTION_INJECT_TEXT: 8496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return mPattern + ": " + Arrays.toString(mResponses); 8596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project case ACTION_CLIENT_CLOSE: 8696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return "Expect the client to close"; 87f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki case ACTION_IO_EXCEPTION: 88f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki return "Expect IOException"; 891a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler case ACTION_START_TLS: 901a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler return "Expect StartTls"; 9196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project default: 9296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return "(Hmm. Unknown action.)"; 9396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 9496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 9596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 96a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 9796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private ArrayList<Transaction> mPairs = new ArrayList<Transaction>(); 98c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 99c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 100c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Give the mock a pattern to wait for. No response will be sent. 101c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * @param pattern Java RegEx to wait for 102c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 103c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler public void expect(String pattern) { 104c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expect(pattern, (String[])null); 105c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 106c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 10796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 10896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Give the mock a pattern to wait for and a response to send back. 10996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * @param pattern Java RegEx to wait for 11096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * @param response String to reply with, or null to acccept string but not respond to it 11196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 11296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void expect(String pattern, String response) { 11396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project expect(pattern, (response == null) ? null : new String[] { response }); 11496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 115a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 11696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 11796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Give the mock a pattern to wait for and a multi-line response to send back. 11896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * @param pattern Java RegEx to wait for 11996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * @param responses Strings to reply with 12096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 12196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void expect(String pattern, String[] responses) { 12296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Transaction pair = new Transaction(pattern, responses); 12396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mPairs.add(pair); 12496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 125af6724527e564d35dd27ac35e24dbced554792e5Makoto Onuki 126af6724527e564d35dd27ac35e24dbced554792e5Makoto Onuki /** 127af6724527e564d35dd27ac35e24dbced554792e5Makoto Onuki * Same as {@link #expect(String, String[])}, but the first arg is taken literally, rather than 128af6724527e564d35dd27ac35e24dbced554792e5Makoto Onuki * as a regexp. 129af6724527e564d35dd27ac35e24dbced554792e5Makoto Onuki */ 130af6724527e564d35dd27ac35e24dbced554792e5Makoto Onuki public void expectLiterally(String literal, String[] responses) { 131af6724527e564d35dd27ac35e24dbced554792e5Makoto Onuki expect("^" + Pattern.quote(literal) + "$", responses); 132af6724527e564d35dd27ac35e24dbced554792e5Makoto Onuki } 133af6724527e564d35dd27ac35e24dbced554792e5Makoto Onuki 134a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki /** 13596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Tell the Mock Transport that we expect it to be closed. This will preserve 13696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * the remaining entries in the expect() stream and allow us to "ride over" the close (which 13796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * would normally reset everything). 13896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 13996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void expectClose() { 14096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mPairs.add(new Transaction(Transaction.ACTION_CLIENT_CLOSE)); 14196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 142a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 143f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki public void expectIOException() { 144f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki mPairs.add(new Transaction(Transaction.ACTION_IO_EXCEPTION)); 145f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki } 146f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki 1471a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler public void expectStartTls() { 1481a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler mPairs.add(new Transaction(Transaction.ACTION_START_TLS)); 1491a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler } 1501a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler 151f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki private void sendResponse(Transaction pair) { 152f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki switch (pair.mAction) { 153f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki case Transaction.ACTION_INJECT_TEXT: 154f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki for (String s : pair.mResponses) { 155f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki mQueuedInput.add(s); 156f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki } 157f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki break; 158f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki case Transaction.ACTION_IO_EXCEPTION: 159f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki mQueuedInput.add(SPECIAL_RESPONSE_IOEXCEPTION); 160f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki break; 161f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki default: 162f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki Assert.fail("Invalid action for sendResponse: " + pair.mAction); 16396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 16496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 16596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 16696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public boolean canTrySslSecurity() { 167e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler return (mConnectionSecurity == CONNECTION_SECURITY_SSL); 16896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 169a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 17096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public boolean canTryTlsSecurity() { 171e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler return (mConnectionSecurity == Transport.CONNECTION_SECURITY_TLS); 17296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 173e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler 174e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler public boolean canTrustAllCertificates() { 175e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler return mTrustCertificates; 176e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler } 177e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler 17896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 1791a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler * Check that TLS was started 1801a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler */ 1811a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler public boolean isTlsStarted() { 1821a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler return mTlsStarted; 1831a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler } 1841a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler 1851a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler /** 186a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki * This simulates a condition where the server has closed its side, causing 18796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * reads to fail. 18896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 18996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void closeInputStream() { 19096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mInputOpen = false; 19196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 19296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 19396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void close() { 19496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mOpen = false; 19596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mInputOpen = false; 19696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // unless it was expected as part of a test, reset the stream 19796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (mPairs.size() > 0) { 19896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Transaction expect = mPairs.remove(0); 19996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (expect.mAction == Transaction.ACTION_CLIENT_CLOSE) { 20096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return; 20196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 20296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 20396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mQueuedInput.clear(); 20496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mPairs.clear(); 20596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 20696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 207cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler /** 208cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler * This is a test function (not part of the interface) and is used to set up a result 209cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler * value for getHost(), if needed for the test. 210cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler */ 211cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler public void setMockHost(String host) { 212cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler mHost = host; 213cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler } 214cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler 21596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public String getHost() { 216cb95fbe13554ee6b4e46d9fd3bcd983e09a688cbAndrew Stadler return mHost; 21796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 21896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 219be2ef97220619a3acf6c3dd4eb4b8add26ff452aAndy Stadler public void setMockLocalAddress(InetAddress address) { 220be2ef97220619a3acf6c3dd4eb4b8add26ff452aAndy Stadler mLocalAddress = address; 221be2ef97220619a3acf6c3dd4eb4b8add26ff452aAndy Stadler } 222be2ef97220619a3acf6c3dd4eb4b8add26ff452aAndy Stadler 22396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public InputStream getInputStream() { 22496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project SmtpSenderUnitTests.assertTrue(mOpen); 22596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return new MockInputStream(); 22696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 22796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 22896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 22996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * This normally serves as a pseudo-clone, for use by Imap. For the purposes of unit testing, 230a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki * until we need something more complex, we'll just return the actual MockTransport. Then we 23196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * don't have to worry about dealing with test metadata like the expects list or socket state. 23296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 23396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public Transport newInstanceWithConfiguration() { 23496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return this; 23596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 23696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 23796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public OutputStream getOutputStream() { 238af6724527e564d35dd27ac35e24dbced554792e5Makoto Onuki Assert.assertTrue(mOpen); 23996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return new MockOutputStream(); 24096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 24196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 24296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public int getPort() { 24396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project SmtpSenderUnitTests.fail("getPort() not implemented"); 24496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return 0; 24596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 24696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 24796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public int getSecurity() { 24896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return mConnectionSecurity; 24996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 25096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 25196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public String[] getUserInfoParts() { 25296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project SmtpSenderUnitTests.fail("getUserInfoParts() not implemented"); 25396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return null; 25496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 25596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 25696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public boolean isOpen() { 25796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return mOpen; 25896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 25996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 26096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void open() /* throws MessagingException, CertificateValidationException */ { 26196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mOpen = true; 26296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mInputOpen = true; 26396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 26496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 26596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 26696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * This returns one string (if available) to the caller. Usually this simply pulls strings 26796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * from the mQueuedInput list, but if the list is empty, we also peek the expect list. This 26896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * supports banners, multi-line responses, and any other cases where we respond without 26996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * a specific expect pattern. 270a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki * 27196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * If no response text is available, we assert (failing our test) as an underflow. 272a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki * 27396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Logs the read text if DEBUG_LOG_STREAMS is true. 27496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 27596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public String readLine() throws IOException { 27696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project SmtpSenderUnitTests.assertTrue(mOpen); 27796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (!mInputOpen) { 27896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project throw new IOException("Reading from MockTransport with closed input"); 27996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 28096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // if there's nothing to read, see if we can find a null-pattern response 281f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki if ((mQueuedInput.size() == 0) && (mPairs.size() > 0)) { 282f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki Transaction pair = mPairs.get(0); 283f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki if (pair.mPattern == null) { 28496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mPairs.remove(0); 285f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki sendResponse(pair); 28696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 28796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 288f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki if (mQueuedInput.size() == 0) { 289f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki // MailTransport returns "" at EOS. 290f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki Log.w(LOG_TAG, "Underflow reading from MockTransport"); 291f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki return ""; 292f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki } 29396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String line = mQueuedInput.remove(0); 29496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (DEBUG_LOG_STREAMS) { 29596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Log.d(LOG_TAG, "<<< " + line); 29696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 297f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki if (SPECIAL_RESPONSE_IOEXCEPTION.equals(line)) { 298f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki throw new IOException("Expected IOException."); 299f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki } 30096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return line; 30196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 30296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 30396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void reopenTls() /* throws MessagingException */ { 30496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project SmtpSenderUnitTests.assertTrue(mOpen); 3051a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler Transaction expect = mPairs.remove(0); 3061a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler SmtpSenderUnitTests.assertTrue(expect.mAction == Transaction.ACTION_START_TLS); 3071a791e675ba5092569125bf09a9fcc721bd4c5e1Andy Stadler mTlsStarted = true; 30896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 30996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 310e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler public void setSecurity(int connectionSecurity, boolean trustAllCertificates) { 31196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mConnectionSecurity = connectionSecurity; 312e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler mTrustCertificates = trustAllCertificates; 31396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 31496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 31596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void setSoTimeout(int timeoutMilliseconds) /* throws SocketException */ { 31696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 317a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 31896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void setUri(URI uri, int defaultPort) { 31996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project SmtpSenderUnitTests.assertTrue("Don't call setUri on a mock transport", false); 32096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 32196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 32296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 32396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Accepts a single string (command or text) that was written by the code under test. 32496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Because we are essentially mocking a server, we check to see if this string was expected. 32596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * If the string was expected, we push the corresponding responses into the mQueuedInput 32696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * list, for subsequent calls to readLine(). If the string does not match, we assert 32796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * the mismatch. If no string was expected, we assert it as an overflow. 328a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki * 32996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Logs the written text if DEBUG_LOG_STREAMS is true. 33096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 331f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki public void writeLine(String s, String sensitiveReplacement) throws IOException { 33296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (DEBUG_LOG_STREAMS) { 33396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Log.d(LOG_TAG, ">>> " + s); 33496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 33596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project SmtpSenderUnitTests.assertTrue(mOpen); 336af6724527e564d35dd27ac35e24dbced554792e5Makoto Onuki SmtpSenderUnitTests.assertTrue("Overflow writing to MockTransport: Getting " + s, 337af6724527e564d35dd27ac35e24dbced554792e5Makoto Onuki 0 != mPairs.size()); 33896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Transaction pair = mPairs.remove(0); 339f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki if (pair.mAction == Transaction.ACTION_IO_EXCEPTION) { 340f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki throw new IOException("Expected IOException."); 341f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki } 342af6724527e564d35dd27ac35e24dbced554792e5Makoto Onuki SmtpSenderUnitTests.assertTrue("Unexpected string written to MockTransport: Actual=" + s 343af6724527e564d35dd27ac35e24dbced554792e5Makoto Onuki + " Expected=" + pair.mPattern, 34496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project pair.mPattern != null && s.matches(pair.mPattern)); 34596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (pair.mResponses != null) { 346f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki sendResponse(pair); 34796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 34896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 349a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 35096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 35196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * This is an InputStream that satisfies the needs of getInputStream() 35296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 35396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private class MockInputStream extends InputStream { 35496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 35596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project byte[] mNextLine = null; 35696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project int mNextIndex = 0; 357a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 35896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 35996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Reads from the same input buffer as readLine() 36096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 36196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project @Override 36296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public int read() throws IOException { 36396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (!mInputOpen) { 36496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project throw new IOException(); 36596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 366a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 36796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (mNextLine != null && mNextIndex < mNextLine.length) { 36896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return mNextLine[mNextIndex++]; 36996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 370a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 37196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // previous line was exhausted so try to get another one 37296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String next = readLine(); 37396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (next == null) { 37496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project throw new IOException("Reading from MockTransport with closed input"); 37596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 37696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mNextLine = (next + "\r\n").getBytes(); 37796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mNextIndex = 0; 37896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 37996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (mNextLine != null && mNextIndex < mNextLine.length) { 38096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return mNextLine[mNextIndex++]; 38196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 382a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 383a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki // no joy - throw an exception 384a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki throw new IOException(); 38596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 38696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 387a599ee773d3bb6350ca775db717123faffbdbfe3Makoto Onuki 38896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 38996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * This is an OutputStream that satisfies the needs of getOutputStream() 39096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 39196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private class MockOutputStream extends OutputStream { 39296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 39396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project StringBuilder sb = new StringBuilder(); 39496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 39596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project @Override 396f255081a85bd1680c6a2d2b7225aa45cd104cb66Makoto Onuki public void write(int oneByte) throws IOException { 397c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // CR or CRLF will immediately dump previous line (w/o CRLF) 398c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler if (oneByte == '\r') { 399c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler writeLine(sb.toString(), null); 400c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler sb = new StringBuilder(); 401c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } else if (oneByte == '\n') { 402c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // swallow it 403c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } else { 40496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project sb.append((char)oneByte); 40596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 40696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 40796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 408be2ef97220619a3acf6c3dd4eb4b8add26ff452aAndy Stadler 409be2ef97220619a3acf6c3dd4eb4b8add26ff452aAndy Stadler public InetAddress getLocalAddress() { 410be2ef97220619a3acf6c3dd4eb4b8add26ff452aAndy Stadler if (isOpen()) { 411be2ef97220619a3acf6c3dd4eb4b8add26ff452aAndy Stadler return mLocalAddress; 412be2ef97220619a3acf6c3dd4eb4b8add26ff452aAndy Stadler } else { 413be2ef97220619a3acf6c3dd4eb4b8add26ff452aAndy Stadler return null; 414be2ef97220619a3acf6c3dd4eb4b8add26ff452aAndy Stadler } 415be2ef97220619a3acf6c3dd4eb4b8add26ff452aAndy Stadler } 41696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project}