commit
9240e25921
4 changed files with 282 additions and 159 deletions
|
@ -161,7 +161,7 @@ class WebDavFolder extends Folder<WebDavMessage> {
|
|||
messageCount = dataset.getMessageCount();
|
||||
}
|
||||
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_WEBDAV) {
|
||||
Log.v(LOG_TAG, "Counted messages and webdav returned: "+messageCount);
|
||||
Log.v(LOG_TAG, "Counted messages and webdav returned: " + messageCount);
|
||||
}
|
||||
|
||||
return messageCount;
|
||||
|
@ -257,7 +257,6 @@ class WebDavFolder extends Folder<WebDavMessage> {
|
|||
headers.put("Brief", "t");
|
||||
headers.put("Range", "rows=" + start + "-" + end);
|
||||
DataSet dataset = store.processRequest(this.mFolderUrl, "SEARCH", messageBody, headers);
|
||||
|
||||
uids = dataset.getUids();
|
||||
Map<String, String> uidToUrl = dataset.getUidToUrl();
|
||||
uidsLength = uids.length;
|
||||
|
@ -354,7 +353,7 @@ class WebDavFolder extends Folder<WebDavMessage> {
|
|||
* associated. Verify and fix that
|
||||
*/
|
||||
if (wdMessage.getUrl().equals("")) {
|
||||
wdMessage.setUrl(getMessageUrls(new String[] { wdMessage.getUid() }).get(wdMessage.getUid()));
|
||||
wdMessage.setUrl(getMessageUrls(new String[]{wdMessage.getUid()}).get(wdMessage.getUid()));
|
||||
Log.i(LOG_TAG, "Fetching messages with UID = '" + wdMessage.getUid() + "', URL = '"
|
||||
+ wdMessage.getUrl() + "'");
|
||||
if (wdMessage.getUrl().equals("")) {
|
||||
|
@ -505,7 +504,7 @@ class WebDavFolder extends Folder<WebDavMessage> {
|
|||
try {
|
||||
wdMessage.setFlagInternal(Flag.SEEN, uidToReadStatus.get(wdMessage.getUid()));
|
||||
} catch (NullPointerException e) {
|
||||
Log.v(LOG_TAG,"Under some weird circumstances, setting the read status when syncing from webdav threw an NPE. Skipping.");
|
||||
Log.v(LOG_TAG, "Under some weird circumstances, setting the read status when syncing from webdav threw an NPE. Skipping.");
|
||||
}
|
||||
|
||||
if (listener != null) {
|
||||
|
@ -532,12 +531,12 @@ class WebDavFolder extends Folder<WebDavMessage> {
|
|||
}
|
||||
|
||||
if (startMessages.size() > 10) {
|
||||
List<WebDavMessage> newMessages = new ArrayList<WebDavMessage>(startMessages.size() - 10);
|
||||
List<WebDavMessage> newMessages = new ArrayList<WebDavMessage>(startMessages.size() - 10);
|
||||
for (int i = 0, count = startMessages.size(); i < count; i++) {
|
||||
if (i < 10) {
|
||||
messages.add(i, startMessages.get(i));
|
||||
} else {
|
||||
newMessages.add(i - 10,startMessages.get(i));
|
||||
newMessages.add(i - 10, startMessages.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ public class WebDavStore extends RemoteStore {
|
|||
|
||||
/**
|
||||
* Decodes a WebDavStore URI.
|
||||
*
|
||||
* <p/>
|
||||
* <p>Possible forms:</p>
|
||||
* <pre>
|
||||
* webdav://user:password@server:port ConnectionSecurity.NONE
|
||||
|
@ -156,11 +156,8 @@ public class WebDavStore extends RemoteStore {
|
|||
/**
|
||||
* Creates a WebDavStore URI with the supplied settings.
|
||||
*
|
||||
* @param server
|
||||
* The {@link ServerSettings} object that holds the server settings.
|
||||
*
|
||||
* @param server The {@link ServerSettings} object that holds the server settings.
|
||||
* @return A WebDavStore URI that holds the same information as the {@code server} parameter.
|
||||
*
|
||||
* @see StoreConfig#getStoreUri()
|
||||
* @see WebDavStore#decodeUri(String)
|
||||
*/
|
||||
|
@ -198,7 +195,7 @@ public class WebDavStore extends RemoteStore {
|
|||
|
||||
try {
|
||||
return new URI(scheme, userInfo, server.host, server.port, uriPath,
|
||||
null, null).toString();
|
||||
null, null).toString();
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IllegalArgumentException("Can't create WebDavStore URI", e);
|
||||
}
|
||||
|
@ -227,7 +224,7 @@ public class WebDavStore extends RemoteStore {
|
|||
private Map<String, WebDavFolder> mFolderList = new HashMap<String, WebDavFolder>();
|
||||
|
||||
public WebDavStore(StoreConfig storeConfig, WebDavHttpClient.WebDavHttpClientFactory clientFactory)
|
||||
throws MessagingException {
|
||||
throws MessagingException {
|
||||
super(storeConfig, null);
|
||||
mHttpClientFactory = clientFactory;
|
||||
|
||||
|
@ -306,7 +303,7 @@ public class WebDavStore extends RemoteStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List <? extends Folder > getPersonalNamespaces(boolean forceListAll) throws MessagingException {
|
||||
public List<? extends Folder> getPersonalNamespaces(boolean forceListAll) throws MessagingException {
|
||||
List<Folder> folderList = new LinkedList<Folder>();
|
||||
/**
|
||||
* We have to check authentication here so we have the proper URL stored
|
||||
|
@ -383,10 +380,9 @@ public class WebDavStore extends RemoteStore {
|
|||
WebDavFolder wdFolder = null;
|
||||
String folderName = getFolderName(folderUrl);
|
||||
if (folderName != null) {
|
||||
if (!this.mFolderList.containsKey(folderName)) {
|
||||
wdFolder = new WebDavFolder(this, folderName);
|
||||
wdFolder = getFolder(folderName);
|
||||
if (wdFolder != null) {
|
||||
wdFolder.setUrl(folderUrl);
|
||||
mFolderList.put(folderName, wdFolder);
|
||||
}
|
||||
}
|
||||
// else: Unknown URL format => NO Folder created
|
||||
|
@ -426,11 +422,12 @@ public class WebDavStore extends RemoteStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Folder getFolder(String name) {
|
||||
public WebDavFolder getFolder(String name) {
|
||||
WebDavFolder folder;
|
||||
|
||||
if ((folder = this.mFolderList.get(name)) == null) {
|
||||
folder = new WebDavFolder(this, name);
|
||||
mFolderList.put(name, folder);
|
||||
}
|
||||
|
||||
return folder;
|
||||
|
@ -494,7 +491,7 @@ public class WebDavStore extends RemoteStore {
|
|||
builder.append("SELECT \"DAV:visiblecount\"\r\n");
|
||||
builder.append(" FROM \"\"\r\n");
|
||||
builder.append(" WHERE \"DAV:ishidden\"=False AND \"DAV:isfolder\"=False AND \"urn:schemas:httpmail:read\"=")
|
||||
.append(messageState).append("\r\n");
|
||||
.append(messageState).append("\r\n");
|
||||
builder.append(" GROUP BY \"DAV:ishidden\"\r\n");
|
||||
builder.append("</a:sql></a:searchrequest>\r\n");
|
||||
return builder.toString();
|
||||
|
@ -632,7 +629,7 @@ public class WebDavStore extends RemoteStore {
|
|||
* @throws MessagingException
|
||||
*/
|
||||
public boolean authenticate()
|
||||
throws MessagingException {
|
||||
throws MessagingException {
|
||||
try {
|
||||
if (mAuthentication == WebDavConstants.AUTH_TYPE_NONE) {
|
||||
ConnectionInfo info = doInitialConnection();
|
||||
|
@ -652,7 +649,7 @@ public class WebDavStore extends RemoteStore {
|
|||
throw new MessagingException("Invalid username or password for authentication.");
|
||||
} else {
|
||||
throw new MessagingException("Error with code " + response.getStatusLine().getStatusCode() +
|
||||
" during request processing: " + response.getStatusLine().toString());
|
||||
" during request processing: " + response.getStatusLine().toString());
|
||||
}
|
||||
} else if (info.requiredAuthType == WebDavConstants.AUTH_TYPE_FORM_BASED) {
|
||||
doFBA(info);
|
||||
|
@ -679,7 +676,7 @@ public class WebDavStore extends RemoteStore {
|
|||
* @throws MessagingException
|
||||
*/
|
||||
private ConnectionInfo doInitialConnection()
|
||||
throws MessagingException {
|
||||
throws MessagingException {
|
||||
// For our initial connection we are sending an empty GET request to
|
||||
// the configured URL, which should be in the following form:
|
||||
// https://mail.server.com/Exchange/alias
|
||||
|
@ -706,8 +703,8 @@ public class WebDavStore extends RemoteStore {
|
|||
// an authentication header for basic authentication.
|
||||
info.requiredAuthType = WebDavConstants.AUTH_TYPE_BASIC;
|
||||
} else if ((info.statusCode >= 200 && info.statusCode < 300) || // Success
|
||||
(info.statusCode >= 300 && info.statusCode < 400) || // Redirect
|
||||
(info.statusCode == 440)) { // Unauthorized
|
||||
(info.statusCode >= 300 && info.statusCode < 400) || // Redirect
|
||||
(info.statusCode == 440)) { // Unauthorized
|
||||
// We will handle all 3 situations the same. First we take an educated
|
||||
// guess at where the authorization DLL is located. If this is this
|
||||
// doesn't work, then we'll use the redirection URL for OWA login given
|
||||
|
@ -730,7 +727,7 @@ public class WebDavStore extends RemoteStore {
|
|||
}
|
||||
} else {
|
||||
throw new IOException("Error with code " + info.statusCode + " during request processing: " +
|
||||
response.getStatusLine().toString());
|
||||
response.getStatusLine().toString());
|
||||
}
|
||||
} catch (SSLException e) {
|
||||
throw new CertificateValidationException(e.getMessage(), e);
|
||||
|
@ -748,9 +745,9 @@ public class WebDavStore extends RemoteStore {
|
|||
* @throws MessagingException
|
||||
*/
|
||||
public void doFBA(ConnectionInfo info)
|
||||
throws IOException, MessagingException {
|
||||
throws IOException, MessagingException {
|
||||
// Clear out cookies from any previous authentication.
|
||||
if(mAuthCookies != null) mAuthCookies.clear();
|
||||
if (mAuthCookies != null) mAuthCookies.clear();
|
||||
|
||||
WebDavHttpClient httpClient = getHttpClient();
|
||||
|
||||
|
@ -820,12 +817,12 @@ public class WebDavStore extends RemoteStore {
|
|||
|
||||
// Reconstruct the login URL based on the original login URL and the form action.
|
||||
URI finalUri = new URI(loginUri.getScheme(),
|
||||
loginUri.getUserInfo(),
|
||||
loginUri.getHost(),
|
||||
loginUri.getPort(),
|
||||
urlPath,
|
||||
null,
|
||||
null);
|
||||
loginUri.getUserInfo(),
|
||||
loginUri.getHost(),
|
||||
loginUri.getPort(),
|
||||
urlPath,
|
||||
null,
|
||||
null);
|
||||
loginUrl = finalUri.toString();
|
||||
}
|
||||
|
||||
|
@ -859,7 +856,7 @@ public class WebDavStore extends RemoteStore {
|
|||
* @throws IOException
|
||||
*/
|
||||
private String findFormAction(InputStream istream)
|
||||
throws IOException {
|
||||
throws IOException {
|
||||
String formAction = null;
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(istream), 4096);
|
||||
|
@ -889,7 +886,7 @@ public class WebDavStore extends RemoteStore {
|
|||
}
|
||||
|
||||
private boolean testAuthenticationResponse(HttpResponse response)
|
||||
throws MessagingException {
|
||||
throws MessagingException {
|
||||
boolean authenticated = false;
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
// Exchange 2007 will return a 302 status code no matter what.
|
||||
|
@ -979,7 +976,7 @@ public class WebDavStore extends RemoteStore {
|
|||
|
||||
private InputStream sendRequest(String url, String method, StringEntity messageBody,
|
||||
Map<String, String> headers, boolean tryAuth)
|
||||
throws MessagingException {
|
||||
throws MessagingException {
|
||||
if (url == null || method == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -1028,7 +1025,7 @@ public class WebDavStore extends RemoteStore {
|
|||
}
|
||||
} else if (statusCode < 200 || statusCode >= 300) {
|
||||
throw new IOException("Error with code " + statusCode + " during request processing: " +
|
||||
response.getStatusLine().toString());
|
||||
response.getStatusLine().toString());
|
||||
}
|
||||
|
||||
if (entity != null) {
|
||||
|
@ -1055,17 +1052,17 @@ public class WebDavStore extends RemoteStore {
|
|||
* response.
|
||||
*/
|
||||
DataSet processRequest(String url, String method, String messageBody, Map<String, String> headers)
|
||||
throws MessagingException {
|
||||
throws MessagingException {
|
||||
return processRequest(url, method, messageBody, headers, true);
|
||||
}
|
||||
|
||||
DataSet processRequest(String url, String method, String messageBody, Map<String, String> headers,
|
||||
boolean needsParsing)
|
||||
throws MessagingException {
|
||||
throws MessagingException {
|
||||
DataSet dataset = new DataSet();
|
||||
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_WEBDAV) {
|
||||
Log.v(LOG_TAG, "processRequest url = '" + url + "', method = '" + method + "', messageBody = '"
|
||||
+ messageBody + "'");
|
||||
+ messageBody + "'");
|
||||
}
|
||||
|
||||
if (url == null ||
|
||||
|
@ -1101,7 +1098,7 @@ public class WebDavStore extends RemoteStore {
|
|||
throw new MessagingException("SAXException in processRequest() ", se);
|
||||
} catch (ParserConfigurationException pce) {
|
||||
Log.e(LOG_TAG, "ParserConfigurationException in processRequest() " + pce + "\nTrace: "
|
||||
+ WebDavUtils.processException(pce));
|
||||
+ WebDavUtils.processException(pce));
|
||||
throw new MessagingException("ParserConfigurationException in processRequest() ", pce);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@ import org.junit.After;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Matchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
|
@ -36,12 +39,14 @@ import static org.junit.Assert.assertNotNull;
|
|||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.anyMap;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
@ -55,6 +60,7 @@ import java.io.InputStream;
|
|||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -76,9 +82,15 @@ public class WebDavFolderTest {
|
|||
private HttpResponse mockHttpResponse;
|
||||
@Mock
|
||||
private StatusLine mockStatusLine;
|
||||
@Captor
|
||||
private ArgumentCaptor<Map<String, String>> headerCaptor;
|
||||
|
||||
private WebDavFolder folder;
|
||||
private File tempDirectory;
|
||||
|
||||
private WebDavFolder destinationFolder;
|
||||
private String moveOrCopyXml = "<xml>MoveOrCopyXml</xml>";
|
||||
private HashMap<String, String> moveOrCopyHeaders;
|
||||
private List<WebDavMessage> messages;
|
||||
|
||||
@Before
|
||||
public void before() throws MessagingException, IOException {
|
||||
|
@ -88,13 +100,16 @@ public class WebDavFolderTest {
|
|||
when(mockStore.getStoreConfig()).thenReturn(mockStoreConfig);
|
||||
folder = new WebDavFolder(mockStore, "testFolder");
|
||||
|
||||
setupTempDirectory();
|
||||
}
|
||||
|
||||
tempDirectory = new File("temp");
|
||||
private void setupTempDirectory() {
|
||||
File tempDirectory = new File("temp");
|
||||
if (!tempDirectory.exists()) {
|
||||
assertTrue(tempDirectory.mkdir());
|
||||
tempDirectory.deleteOnExit();
|
||||
}
|
||||
BinaryTempFileBody.setTempDirectory(new File("temp"));
|
||||
BinaryTempFileBody.setTempDirectory(tempDirectory);
|
||||
}
|
||||
|
||||
private WebDavFolder setupDestinationFolder() {
|
||||
|
@ -103,14 +118,31 @@ public class WebDavFolderTest {
|
|||
return destinationFolder;
|
||||
}
|
||||
|
||||
private void verifyUrlMappingRequest(String uid, String url) throws MessagingException {
|
||||
private void setupFolderWithMessages(int count) throws MessagingException {
|
||||
HashMap<String, String> headers = new HashMap<>();
|
||||
headers.put("Brief", "t");
|
||||
String messageCountXml = "<xml>MessageCountXml</xml>";
|
||||
when(mockStore.getMessageCountXml("True")).thenReturn(messageCountXml);
|
||||
when(mockStore.processRequest("https://localhost/webDavStoreUrl/testFolder",
|
||||
"SEARCH", messageCountXml, headers)).thenReturn(mockDataSet);
|
||||
when(mockDataSet.getMessageCount()).thenReturn(count);
|
||||
folder.getMessageCount();
|
||||
}
|
||||
|
||||
private WebDavMessage createWebDavMessage(String uid) {
|
||||
WebDavMessage webDavMessage = mock(WebDavMessage.class);
|
||||
when(webDavMessage.getUid()).thenReturn(uid);
|
||||
return webDavMessage;
|
||||
}
|
||||
|
||||
private void setupGetUrlsRequestResponse(String uid, String url) throws MessagingException {
|
||||
String getUrlsXml = "<xml>GetUrls</xml>";
|
||||
when(mockStore.getMessageUrlsXml(new String[]{uid})).thenReturn(getUrlsXml);
|
||||
HashMap<String, String> headers = new HashMap<>();
|
||||
headers.put("Brief", "t");
|
||||
when(mockStore.processRequest("https://localhost/webDavStoreUrl/testFolder", "SEARCH", getUrlsXml, headers))
|
||||
.thenReturn(mockDataSet);
|
||||
Map<String, String> urlUids = new HashMap<String,String>();
|
||||
Map<String, String> urlUids = new HashMap<String, String>();
|
||||
urlUids.put(uid, url);
|
||||
when(mockDataSet.getUidToUrl()).thenReturn(urlUids);
|
||||
}
|
||||
|
@ -121,7 +153,7 @@ public class WebDavFolderTest {
|
|||
.thenReturn(mockDataSet);
|
||||
|
||||
List<WebDavMessage> messages = new ArrayList<>();
|
||||
for(int i = 0; i < 5; i++) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
WebDavMessage mockMessage = mock(WebDavMessage.class);
|
||||
messages.add(mockMessage);
|
||||
}
|
||||
|
@ -137,7 +169,7 @@ public class WebDavFolderTest {
|
|||
.thenReturn(mockDataSet);
|
||||
|
||||
List<WebDavMessage> messages = new ArrayList<>();
|
||||
for(int i = 0; i < 15; i++) {
|
||||
for (int i = 0; i < 15; i++) {
|
||||
WebDavMessage mockMessage = mock(WebDavMessage.class);
|
||||
messages.add(mockMessage);
|
||||
}
|
||||
|
@ -152,7 +184,7 @@ public class WebDavFolderTest {
|
|||
.thenReturn(mockDataSet);
|
||||
|
||||
List<WebDavMessage> messages = new ArrayList<>();
|
||||
for(int i = 0; i < 5; i++) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
WebDavMessage mockMessage = mock(WebDavMessage.class);
|
||||
messages.add(mockMessage);
|
||||
}
|
||||
|
@ -167,7 +199,7 @@ public class WebDavFolderTest {
|
|||
.thenReturn(mockDataSet);
|
||||
|
||||
List<WebDavMessage> messages = new ArrayList<>();
|
||||
for(int i = 0; i < 25; i++) {
|
||||
for (int i = 0; i < 25; i++) {
|
||||
WebDavMessage mockMessage = mock(WebDavMessage.class);
|
||||
messages.add(mockMessage);
|
||||
}
|
||||
|
@ -179,26 +211,26 @@ public class WebDavFolderTest {
|
|||
|
||||
@Test
|
||||
public void folder_can_fetch_sensible_body_data_and_notifies_listener()
|
||||
throws MessagingException, IOException, URISyntaxException {
|
||||
throws MessagingException, IOException, URISyntaxException {
|
||||
setupStoreForMessageFetching();
|
||||
List<WebDavMessage> messages = setup25MessagesToFetch();
|
||||
|
||||
when(mockHttpClient.executeOverride(any(HttpUriRequest.class), any(HttpContext.class))).thenAnswer(
|
||||
new Answer<HttpResponse>() {
|
||||
@Override
|
||||
public HttpResponse answer(InvocationOnMock invocation) throws Throwable {
|
||||
HttpResponse httpResponse = mock(HttpResponse.class);
|
||||
StatusLine statusLine = mock(StatusLine.class);
|
||||
when(httpResponse.getStatusLine()).thenReturn(statusLine);
|
||||
when(statusLine.getStatusCode()).thenReturn(200);
|
||||
new Answer<HttpResponse>() {
|
||||
@Override
|
||||
public HttpResponse answer(InvocationOnMock invocation) throws Throwable {
|
||||
HttpResponse httpResponse = mock(HttpResponse.class);
|
||||
StatusLine statusLine = mock(StatusLine.class);
|
||||
when(httpResponse.getStatusLine()).thenReturn(statusLine);
|
||||
when(statusLine.getStatusCode()).thenReturn(200);
|
||||
|
||||
BasicHttpEntity httpEntity = new BasicHttpEntity();
|
||||
String body = "";
|
||||
httpEntity.setContent(new ByteArrayInputStream(body.getBytes("UTF-8")));
|
||||
when(httpResponse.getEntity()).thenReturn(httpEntity);
|
||||
return httpResponse;
|
||||
}
|
||||
});
|
||||
BasicHttpEntity httpEntity = new BasicHttpEntity();
|
||||
String body = "";
|
||||
httpEntity.setContent(new ByteArrayInputStream(body.getBytes("UTF-8")));
|
||||
when(httpResponse.getEntity()).thenReturn(httpEntity);
|
||||
return httpResponse;
|
||||
}
|
||||
});
|
||||
|
||||
FetchProfile profile = new FetchProfile();
|
||||
profile.add(FetchProfile.Item.BODY_SANE);
|
||||
|
@ -217,9 +249,9 @@ public class WebDavFolderTest {
|
|||
private List<WebDavMessage> setup25MessagesToFetch() {
|
||||
|
||||
List<WebDavMessage> messages = new ArrayList<>();
|
||||
for(int i = 0; i < 25; i++) {
|
||||
WebDavMessage message = new WebDavMessage("message"+i, folder);
|
||||
message.setUrl("http://example.org/Exchange/user/Inbox/message"+i+".EML");
|
||||
for (int i = 0; i < 25; i++) {
|
||||
WebDavMessage message = new WebDavMessage("message" + i, folder);
|
||||
message.setUrl("http://example.org/Exchange/user/Inbox/message" + i + ".EML");
|
||||
messages.add(message);
|
||||
}
|
||||
return messages;
|
||||
|
@ -231,16 +263,16 @@ public class WebDavFolderTest {
|
|||
List<WebDavMessage> messages = setup25MessagesToFetch();
|
||||
|
||||
when(mockHttpClient.executeOverride(any(HttpUriRequest.class), any(HttpContext.class))).thenAnswer(
|
||||
new Answer<HttpResponse>() {
|
||||
@Override
|
||||
public HttpResponse answer(InvocationOnMock invocation) throws Throwable {
|
||||
HttpResponse httpResponse = mock(HttpResponse.class);
|
||||
StatusLine statusLine = mock(StatusLine.class);
|
||||
when(httpResponse.getStatusLine()).thenReturn(statusLine);
|
||||
when(statusLine.getStatusCode()).thenReturn(200);
|
||||
return httpResponse;
|
||||
}
|
||||
});
|
||||
new Answer<HttpResponse>() {
|
||||
@Override
|
||||
public HttpResponse answer(InvocationOnMock invocation) throws Throwable {
|
||||
HttpResponse httpResponse = mock(HttpResponse.class);
|
||||
StatusLine statusLine = mock(StatusLine.class);
|
||||
when(httpResponse.getStatusLine()).thenReturn(statusLine);
|
||||
when(statusLine.getStatusCode()).thenReturn(200);
|
||||
return httpResponse;
|
||||
}
|
||||
});
|
||||
|
||||
FetchProfile profile = new FetchProfile();
|
||||
profile.add(FetchProfile.Item.BODY_SANE);
|
||||
|
@ -255,23 +287,23 @@ public class WebDavFolderTest {
|
|||
List<WebDavMessage> messages = setup25MessagesToFetch();
|
||||
|
||||
when(mockHttpClient.executeOverride(any(HttpUriRequest.class), any(HttpContext.class))).thenAnswer(
|
||||
new Answer<HttpResponse>() {
|
||||
@Override
|
||||
public HttpResponse answer(InvocationOnMock invocation) throws Throwable {
|
||||
HttpResponse httpResponse = mock(HttpResponse.class);
|
||||
StatusLine statusLine = mock(StatusLine.class);
|
||||
when(httpResponse.getStatusLine()).thenReturn(statusLine);
|
||||
when(statusLine.getStatusCode()).thenReturn(200);
|
||||
new Answer<HttpResponse>() {
|
||||
@Override
|
||||
public HttpResponse answer(InvocationOnMock invocation) throws Throwable {
|
||||
HttpResponse httpResponse = mock(HttpResponse.class);
|
||||
StatusLine statusLine = mock(StatusLine.class);
|
||||
when(httpResponse.getStatusLine()).thenReturn(statusLine);
|
||||
when(statusLine.getStatusCode()).thenReturn(200);
|
||||
|
||||
BasicHttpEntity httpEntity = new BasicHttpEntity();
|
||||
InputStream mockInputStream = mock(InputStream.class);
|
||||
when(mockInputStream.read(any(byte[].class), anyInt(), anyInt())).thenReturn(1).thenReturn(-1);
|
||||
doThrow(new IOException("Test")).when(mockInputStream).close();
|
||||
httpEntity.setContent(mockInputStream);
|
||||
when(httpResponse.getEntity()).thenReturn(httpEntity);
|
||||
return httpResponse;
|
||||
}
|
||||
});
|
||||
BasicHttpEntity httpEntity = new BasicHttpEntity();
|
||||
InputStream mockInputStream = mock(InputStream.class);
|
||||
when(mockInputStream.read(any(byte[].class), anyInt(), anyInt())).thenReturn(1).thenReturn(-1);
|
||||
doThrow(new IOException("Test")).when(mockInputStream).close();
|
||||
httpEntity.setContent(mockInputStream);
|
||||
when(httpResponse.getEntity()).thenReturn(httpEntity);
|
||||
return httpResponse;
|
||||
}
|
||||
});
|
||||
|
||||
FetchProfile profile = new FetchProfile();
|
||||
profile.add(FetchProfile.Item.BODY_SANE);
|
||||
|
@ -311,74 +343,146 @@ public class WebDavFolderTest {
|
|||
|
||||
@Test
|
||||
public void can_fetch_message_count() throws Exception {
|
||||
int messageCount = 23;
|
||||
HashMap<String, String> headers = new HashMap<>();
|
||||
headers.put("Brief", "t");
|
||||
String messageCountXml = "<xml>MessageCountXml</xml>";
|
||||
when(mockStore.getMessageCountXml("True")).thenReturn(messageCountXml);
|
||||
when(mockStore.processRequest("https://localhost/webDavStoreUrl/testFolder",
|
||||
"SEARCH", messageCountXml, headers)).thenReturn(mockDataSet);
|
||||
when(mockDataSet.getMessageCount()).thenReturn(23);
|
||||
assertEquals(23, folder.getMessageCount());
|
||||
when(mockDataSet.getMessageCount()).thenReturn(messageCount);
|
||||
|
||||
int result = folder.getMessageCount();
|
||||
|
||||
assertEquals(messageCount, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void can_fetch_unread_message_count() throws Exception {
|
||||
int unreadMessageCount = 13;
|
||||
HashMap<String, String> headers = new HashMap<>();
|
||||
headers.put("Brief", "t");
|
||||
String messageCountXml = "<xml>MessageCountXml</xml>";
|
||||
when(mockStore.getMessageCountXml("False")).thenReturn(messageCountXml);
|
||||
when(mockStore.processRequest("https://localhost/webDavStoreUrl/testFolder",
|
||||
"SEARCH", messageCountXml, headers)).thenReturn(mockDataSet);
|
||||
when(mockDataSet.getMessageCount()).thenReturn(13);
|
||||
assertEquals(13, folder.getUnreadMessageCount());
|
||||
when(mockDataSet.getMessageCount()).thenReturn(unreadMessageCount);
|
||||
|
||||
int result = folder.getUnreadMessageCount();
|
||||
|
||||
assertEquals(unreadMessageCount, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMessages_should_request_message_search() throws MessagingException {
|
||||
int totalMessages = 23;
|
||||
int messageStart = 1;
|
||||
int messageEnd = 11;
|
||||
setupFolderWithMessages(totalMessages);
|
||||
String messagesXml = "<xml>MessagesXml</xml>";
|
||||
buildSearchResponse(mockDataSet);
|
||||
when(mockStore.getMessagesXml()).thenReturn(messagesXml);
|
||||
when(mockStore.processRequest(eq("https://localhost/webDavStoreUrl/testFolder"), eq("SEARCH"),
|
||||
eq(messagesXml), Matchers.<Map<String, String>>any())).thenReturn(mockDataSet);
|
||||
|
||||
folder.getMessages(1, 11, new Date(), listener);
|
||||
|
||||
verify(listener, times(5)).messageStarted(anyString(), anyInt(), eq(5));
|
||||
verify(listener, times(5)).messageFinished(any(WebDavMessage.class), anyInt(), eq(5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMessages_shouldProvideCorrectHeadersInRequest() throws MessagingException {
|
||||
int totalMessages = 23;
|
||||
int messageStart = 1;
|
||||
int messageEnd = 11;
|
||||
setupFolderWithMessages(totalMessages);
|
||||
String messagesXml = "<xml>MessagesXml</xml>";
|
||||
buildSearchResponse(mockDataSet);
|
||||
when(mockStore.getMessagesXml()).thenReturn(messagesXml);
|
||||
when(mockStore.processRequest(eq("https://localhost/webDavStoreUrl/testFolder"), eq("SEARCH"),
|
||||
eq(messagesXml), Matchers.<Map<String, String>>any())).thenReturn(mockDataSet);
|
||||
|
||||
folder.getMessages(messageStart, messageEnd, new Date(), listener);
|
||||
|
||||
verify(mockStore, times(2)).processRequest(anyString(), anyString(), anyString(),
|
||||
headerCaptor.capture());
|
||||
assertEquals(2, headerCaptor.getValue().size());
|
||||
assertEquals("t", headerCaptor.getValue().get("Brief"));
|
||||
assertEquals("rows=" + (totalMessages - (messageEnd)) + "-" + (totalMessages - messageStart)
|
||||
, headerCaptor.getValue().get("Range"));
|
||||
}
|
||||
|
||||
private void buildSearchResponse(DataSet mockDataSet) {
|
||||
String[] uids = new String[]{"uid1", "uid2", "uid3", "uid4", "uid5"};
|
||||
HashMap<String, String> uidToUrls = new HashMap<>();
|
||||
uidToUrls.put("uid1", "url1");
|
||||
uidToUrls.put("uid2", "url2");
|
||||
uidToUrls.put("uid3", "url3");
|
||||
uidToUrls.put("uid4", "url4");
|
||||
uidToUrls.put("uid5", "url5");
|
||||
|
||||
when(mockDataSet.getUids()).thenReturn(uids);
|
||||
when(mockDataSet.getUidToUrl()).thenReturn(uidToUrls);
|
||||
}
|
||||
|
||||
@Test(expected = MessagingException.class)
|
||||
public void getMessages_should_throw_message_exception_if_requesting_messages_from_empty_folder()
|
||||
throws MessagingException {
|
||||
folder.getMessages(0, 10, new Date(), listener);
|
||||
}
|
||||
|
||||
private void setupMoveOrCopy() throws MessagingException {
|
||||
destinationFolder = setupDestinationFolder();
|
||||
String uid = "uid1";
|
||||
String url = "url1";
|
||||
messages = singletonList(createWebDavMessage(uid));
|
||||
setupGetUrlsRequestResponse(uid, url);
|
||||
when(mockStore.getMoveOrCopyMessagesReadXml(eq(new String[]{url}), anyBoolean())).thenReturn(moveOrCopyXml);
|
||||
moveOrCopyHeaders = new HashMap<>();
|
||||
moveOrCopyHeaders.put("Destination", "https://localhost/webDavStoreUrl/destFolder");
|
||||
moveOrCopyHeaders.put("Brief", "t");
|
||||
moveOrCopyHeaders.put("If-Match", "*");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void moveMessages_should_requestMoveXml() throws Exception {
|
||||
setupMoveOrCopy();
|
||||
|
||||
folder.moveMessages(messages, destinationFolder);
|
||||
|
||||
verify(mockStore).getMoveOrCopyMessagesReadXml(eq(new String[]{"url1"}),
|
||||
eq(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void moveMessages_should_send_move_command() throws Exception {
|
||||
WebDavFolder destinationFolder = setupDestinationFolder();
|
||||
String uid = "uid1";
|
||||
String url = "url1";
|
||||
List<WebDavMessage> messages = singletonList(createWebDavMessage(uid));
|
||||
verifyUrlMappingRequest(uid, url);
|
||||
setupMoveOrCopy();
|
||||
|
||||
String moveOrCopyXml = "<xml>MoveOrCopyXml</xml>";
|
||||
when(mockStore.getMoveOrCopyMessagesReadXml(new String[]{url}, true)).thenReturn(moveOrCopyXml);
|
||||
HashMap<String, String> headers = new HashMap<>();
|
||||
headers.put("Destination", "https://localhost/webDavStoreUrl/destFolder");
|
||||
headers.put("Brief", "t");
|
||||
headers.put("If-Match", "*");
|
||||
when(mockStore.processRequest("https://localhost/webDavStoreUrl/testFolder", "BMOVE", moveOrCopyXml, headers, false))
|
||||
.thenReturn(mockDataSet);
|
||||
folder.moveMessages(messages, destinationFolder);
|
||||
|
||||
Map<String, String> result = folder.moveMessages(messages, destinationFolder);
|
||||
assertNull(result);
|
||||
verify(mockStore).processRequest("https://localhost/webDavStoreUrl/testFolder", "BMOVE",
|
||||
moveOrCopyXml, moveOrCopyHeaders, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyMessages_should_requestCopyXml() throws Exception {
|
||||
setupMoveOrCopy();
|
||||
|
||||
folder.copyMessages(messages, destinationFolder);
|
||||
|
||||
verify(mockStore).getMoveOrCopyMessagesReadXml(eq(new String[]{"url1"}),
|
||||
eq(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyMessages_should_send_copy_command() throws Exception {
|
||||
WebDavFolder destinationFolder = setupDestinationFolder();
|
||||
String uid = "uid1";
|
||||
String url = "url1";
|
||||
List<WebDavMessage> messages = singletonList(createWebDavMessage(uid));
|
||||
verifyUrlMappingRequest(uid, url);
|
||||
setupMoveOrCopy();
|
||||
|
||||
folder.copyMessages(messages, destinationFolder);
|
||||
|
||||
String moveOrCopyXml = "<xml>MoveOrCopyXml</xml>";
|
||||
when(mockStore.getMoveOrCopyMessagesReadXml(new String[]{url},false)).thenReturn(moveOrCopyXml);
|
||||
HashMap<String, String> headers = new HashMap<>();
|
||||
headers.put("Destination", "https://localhost/webDavStoreUrl/destFolder");
|
||||
headers.put("Brief", "t");
|
||||
headers.put("If-Match", "*");
|
||||
when(mockStore.processRequest("https://localhost/webDavStoreUrl/testFolder", "COPY", moveOrCopyXml, headers, false))
|
||||
.thenReturn(mockDataSet);
|
||||
Map<String, String> result = folder.copyMessages(messages, destinationFolder);
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
private WebDavMessage createWebDavMessage(String uid) {
|
||||
WebDavMessage webDavMessage = mock(WebDavMessage.class);
|
||||
when(webDavMessage.getUid()).thenReturn(uid);
|
||||
return webDavMessage;
|
||||
verify(mockStore).processRequest("https://localhost/webDavStoreUrl/testFolder", "BCOPY",
|
||||
moveOrCopyXml, moveOrCopyHeaders, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -386,7 +490,6 @@ public class WebDavFolderTest {
|
|||
when(mockHttpClient.executeOverride(any(HttpUriRequest.class), any(HttpContext.class))).thenReturn(mockHttpResponse);
|
||||
when(mockHttpResponse.getStatusLine()).thenReturn(mockStatusLine);
|
||||
when(mockStatusLine.getStatusCode()).thenReturn(200);
|
||||
|
||||
List<Message> existingMessages = new ArrayList<>();
|
||||
Message existingMessage = mock(Message.class);
|
||||
existingMessages.add(existingMessage);
|
||||
|
|
|
@ -16,7 +16,9 @@ import com.fsck.k9.mail.ServerSettings;
|
|||
import com.fsck.k9.mail.ServerSettings.Type;
|
||||
import com.fsck.k9.mail.filter.Base64;
|
||||
import com.fsck.k9.mail.store.StoreConfig;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpVersion;
|
||||
|
@ -45,6 +47,9 @@ import org.mockito.stubbing.OngoingStubbing;
|
|||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static junit.framework.Assert.assertSame;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
@ -104,22 +109,6 @@ public class WebDavStoreTest {
|
|||
assertEquals("webdav+ssl+://user:password@example.org:123456/%7C%7C", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createUri_withSettingsWithExtras_shouldProvideUriWithExtras() {
|
||||
HashMap<String, String> extras = new HashMap<>();
|
||||
extras.put(WebDavStoreSettings.PATH_KEY, "path");
|
||||
extras.put(WebDavStoreSettings.AUTH_PATH_KEY, "authPath");
|
||||
extras.put(WebDavStoreSettings.MAILBOX_PATH_KEY, "mailboxPath");
|
||||
ServerSettings serverSettings = new ServerSettings(
|
||||
ServerSettings.Type.WebDAV, "example.org", 123456,
|
||||
ConnectionSecurity.NONE, AuthType.PLAIN,
|
||||
"user", "password", null, extras);
|
||||
|
||||
String result = WebDavStore.createUri(serverSettings);
|
||||
|
||||
assertEquals("webdav://user:password@example.org:123456/path%7CauthPath%7CmailboxPath", result);
|
||||
}
|
||||
|
||||
@Test(expected = MessagingException.class)
|
||||
public void constructor_withImapStoreUri_shouldThrow() throws Exception {
|
||||
StoreConfig storeConfig = createStoreConfig("imap://user:password@imap.example.org");
|
||||
|
@ -253,7 +242,6 @@ public class WebDavStoreTest {
|
|||
assertEquals(WebDavFolder.class, result.getClass());
|
||||
}
|
||||
|
||||
//FIXME: This doesn't check if the same instance is returned. Fails when changed to use assertSame().
|
||||
@Test
|
||||
public void getFolder_calledTwice_shouldReturnFirstInstance() throws Exception {
|
||||
WebDavStore webDavStore = createDefaultWebDavStore();
|
||||
|
@ -262,12 +250,51 @@ public class WebDavStoreTest {
|
|||
|
||||
Folder result = webDavStore.getFolder(folderName);
|
||||
|
||||
assertEquals(webDavFolder, result);
|
||||
assertSame(webDavFolder, result);
|
||||
}
|
||||
|
||||
//TODO: Break apart. This is testing more than one thing.
|
||||
@Test
|
||||
public void getPersonalNamespaces_shouldProvideListOfAllFolders() throws Exception {
|
||||
public void getPersonalNamespaces_shouldRequestSpecialFolders() throws Exception {
|
||||
StoreConfig storeConfig = createStoreConfig("webdav://user:password@example.org:80");
|
||||
WebDavStore webDavStore = new WebDavStore(storeConfig, mockHttpClientFactory);
|
||||
configureHttpResponses(UNAUTHORIZED_401_RESPONSE, OK_200_RESPONSE, createOkPropfindResponse(),
|
||||
createOkSearchResponse());
|
||||
|
||||
webDavStore.getPersonalNamespaces(true);
|
||||
|
||||
List<HttpGeneric> requests = requestCaptor.getAllValues();
|
||||
assertEquals(4, requests.size()); // AUTH + 2
|
||||
assertEquals("PROPFIND", requests.get(2).getMethod()); //Special Folders
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPersonalNamespaces_shouldSetSpecialFolderNames() throws Exception {
|
||||
StoreConfig storeConfig = createStoreConfig("webdav://user:password@example.org:80");
|
||||
WebDavStore webDavStore = new WebDavStore(storeConfig, mockHttpClientFactory);
|
||||
configureHttpResponses(UNAUTHORIZED_401_RESPONSE, OK_200_RESPONSE, createOkPropfindResponse(),
|
||||
createOkSearchResponse());
|
||||
|
||||
webDavStore.getPersonalNamespaces(true);
|
||||
|
||||
verify(storeConfig).setInboxFolderName("Inbox");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPersonalNamespaces_shouldRequestFolderList() throws Exception {
|
||||
StoreConfig storeConfig = createStoreConfig("webdav://user:password@example.org:80");
|
||||
WebDavStore webDavStore = new WebDavStore(storeConfig, mockHttpClientFactory);
|
||||
configureHttpResponses(UNAUTHORIZED_401_RESPONSE, OK_200_RESPONSE, createOkPropfindResponse(),
|
||||
createOkSearchResponse());
|
||||
|
||||
webDavStore.getPersonalNamespaces(true);
|
||||
|
||||
List<HttpGeneric> requests = requestCaptor.getAllValues();
|
||||
assertEquals(4, requests.size()); // AUTH + SPECIALFOLDERS + 1
|
||||
assertEquals("SEARCH", requests.get(3).getMethod());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPersonalNamespaces_shouldProvideListOfAllFoldersSentFromResponses() throws Exception {
|
||||
StoreConfig storeConfig = createStoreConfig("webdav://user:password@example.org:80");
|
||||
WebDavStore webDavStore = new WebDavStore(storeConfig, mockHttpClientFactory);
|
||||
configureHttpResponses(UNAUTHORIZED_401_RESPONSE, OK_200_RESPONSE, createOkPropfindResponse(),
|
||||
|
@ -275,11 +302,8 @@ public class WebDavStoreTest {
|
|||
|
||||
List<? extends Folder> folders = webDavStore.getPersonalNamespaces(true);
|
||||
|
||||
verify(storeConfig).setInboxFolderName("Inbox");
|
||||
List<HttpGeneric> requests = requestCaptor.getAllValues();
|
||||
assertEquals(4, requests.size()); // AUTH + 2
|
||||
assertEquals("PROPFIND", requests.get(2).getMethod()); //Special Folders
|
||||
assertEquals("SEARCH", requests.get(3).getMethod()); //Folder List
|
||||
|
||||
assertEquals(3, folders.size());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue