Java tutorial
/* * Copyright 2013 2015 Ricki Hirner (bitfire web engineering). * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html */ package at.bitfire.davdroid.webdav; import android.content.res.AssetManager; import android.test.InstrumentationTestCase; import org.apache.commons.io.IOUtils; import org.apache.http.impl.client.CloseableHttpClient; import java.io.InputStream; import java.net.URI; import java.util.Arrays; import javax.net.ssl.SSLPeerUnverifiedException; import at.bitfire.davdroid.TestConstants; import at.bitfire.davdroid.webdav.HttpPropfind.Mode; import at.bitfire.davdroid.webdav.WebDavResource.PutMode; import ezvcard.VCardVersion; import lombok.Cleanup; // tests require running robohydra! public class WebDavResourceTest extends InstrumentationTestCase { final static byte[] SAMPLE_CONTENT = new byte[] { 1, 2, 3, 4, 5 }; AssetManager assetMgr; CloseableHttpClient httpClient; WebDavResource baseDAV; WebDavResource davAssets, davCollection, davNonExistingFile, davExistingFile; @Override protected void setUp() throws Exception { httpClient = DavHttpClient.create(); assetMgr = getInstrumentation().getContext().getResources().getAssets(); baseDAV = new WebDavResource(httpClient, TestConstants.roboHydra.resolve("/dav/")); davAssets = new WebDavResource(httpClient, TestConstants.roboHydra.resolve("assets/")); davCollection = new WebDavResource(httpClient, TestConstants.roboHydra.resolve("dav/")); davNonExistingFile = new WebDavResource(davCollection, "collection/new.file"); davExistingFile = new WebDavResource(davCollection, "collection/existing.file"); } @Override protected void tearDown() throws Exception { httpClient.close(); } /* test feature detection */ public void testOptions() throws Exception { String[] davMethods = new String[] { "PROPFIND", "GET", "PUT", "DELETE", "REPORT" }, davCapabilities = new String[] { "addressbook", "calendar-access" }; WebDavResource capable = new WebDavResource(baseDAV); capable.options(); for (String davMethod : davMethods) assertTrue(capable.supportsMethod(davMethod)); for (String capability : davCapabilities) assertTrue(capable.supportsDAV(capability)); } public void testPropfindCurrentUserPrincipal() throws Exception { davCollection.propfind(HttpPropfind.Mode.CURRENT_USER_PRINCIPAL); assertEquals(new URI("/dav/principals/users/test"), davCollection.getProperties().getCurrentUserPrincipal()); WebDavResource simpleFile = new WebDavResource(davAssets, "test.random"); try { simpleFile.propfind(HttpPropfind.Mode.CURRENT_USER_PRINCIPAL); fail(); } catch (DavException ex) { } assertNull(simpleFile.getProperties().getCurrentUserPrincipal()); } public void testPropfindHomeSets() throws Exception { WebDavResource dav = new WebDavResource(davCollection, "principals/users/test"); dav.propfind(HttpPropfind.Mode.HOME_SETS); assertEquals(new URI("/dav/addressbooks/test/"), dav.getProperties().getAddressbookHomeSet()); assertEquals(new URI("/dav/calendars/test/"), dav.getProperties().getCalendarHomeSet()); } public void testPropfindAddressBooks() throws Exception { WebDavResource dav = new WebDavResource(davCollection, "addressbooks/test"); dav.propfind(HttpPropfind.Mode.CARDDAV_COLLECTIONS); // there should be two address books assertEquals(3, dav.getMembers().size()); // the first one is not an address book and not even a collection (referenced by relative URI) WebDavResource ab = dav.getMembers().get(0); assertEquals(TestConstants.roboHydra.resolve("/dav/addressbooks/test/useless-member"), ab.getLocation()); assertEquals("useless-member", ab.getName()); assertFalse(ab.getProperties().isAddressBook()); // the second one is an address book (referenced by relative URI) ab = dav.getMembers().get(1); assertEquals(TestConstants.roboHydra.resolve("/dav/addressbooks/test/default.vcf/"), ab.getLocation()); assertEquals("default.vcf", ab.getName()); assertTrue(ab.getProperties().isAddressBook()); // the third one is an address book (referenced by an absolute URI) ab = dav.getMembers().get(2); assertEquals(new URI("https://my.server/absolute:uri/my-address-book/"), ab.getLocation()); assertEquals("my-address-book", ab.getName()); assertTrue(ab.getProperties().isAddressBook()); } public void testPropfindCalendars() throws Exception { WebDavResource dav = new WebDavResource(davCollection, "calendars/test"); dav.propfind(Mode.CALDAV_COLLECTIONS); assertEquals(3, dav.getMembers().size()); assertEquals(new Integer(0xFFFF00FF), dav.getMembers().get(2).getProperties().getColor()); for (WebDavResource member : dav.getMembers()) { if (member.getName().contains(".ics")) assertTrue(member.getProperties().isCalendar()); else assertFalse(member.getProperties().isCalendar()); assertFalse(member.getProperties().isAddressBook()); } } public void testPropfindCollectionProperties() throws Exception { WebDavResource dav = new WebDavResource(davCollection, "propfind-collection-properties"); dav.propfind(Mode.COLLECTION_PROPERTIES); assertTrue(dav.members.isEmpty()); assertTrue(dav.properties.isCollection); assertTrue(dav.properties.isAddressBook); assertNull(dav.properties.displayName); assertNull(dav.properties.color); assertEquals(VCardVersion.V4_0, dav.properties.supportedVCardVersion); } public void testPropfindTrailingSlashes() throws Exception { final String principalOK = "/principals/ok"; String requestPaths[] = { "/dav/collection-response-with-trailing-slash", "/dav/collection-response-with-trailing-slash/", "/dav/collection-response-without-trailing-slash", "/dav/collection-response-without-trailing-slash/" }; for (String path : requestPaths) { WebDavResource davSlash = new WebDavResource(davCollection, new URI(path)); davSlash.propfind(Mode.CARDDAV_COLLECTIONS); assertEquals(new URI(principalOK), davSlash.getProperties().getCurrentUserPrincipal()); } } public void testStrangeMemberNames() throws Exception { // construct a WebDavResource from a base collection and a member which is an encoded URL (see https://github.com/bitfireAT/davdroid/issues/482) WebDavResource dav = new WebDavResource(davCollection, "http%3A%2F%2Fwww.invalid.example%2Fm8%2Ffeeds%2Fcontacts%2Fmaria.mueller%2540gmail.com%2Fbase%2F5528abc5720cecc.vcf"); dav.get("text/vcard"); } /* test normal HTTP/WebDAV */ public void testPropfindRedirection() throws Exception { // PROPFIND redirection WebDavResource redirected = new WebDavResource(baseDAV, new URI("/redirect/301?to=/dav/")); redirected.propfind(Mode.CURRENT_USER_PRINCIPAL); assertEquals("/dav/", redirected.getLocation().getPath()); } public void testGet() throws Exception { WebDavResource simpleFile = new WebDavResource(davAssets, "test.random"); simpleFile.get("*/*"); @Cleanup InputStream is = assetMgr.open("test.random", AssetManager.ACCESS_STREAMING); byte[] expected = IOUtils.toByteArray(is); assertTrue(Arrays.equals(expected, simpleFile.getContent())); } public void testGetHttpsWithSni() throws Exception { WebDavResource file = new WebDavResource(httpClient, new URI("https://sni.velox.ch")); boolean sniWorking = false; try { file.get("* /*"); sniWorking = true; } catch (SSLPeerUnverifiedException e) { } assertTrue(sniWorking); } public void testMultiGet() throws Exception { WebDavResource davAddressBook = new WebDavResource(davCollection, "addressbooks/default.vcf/"); davAddressBook.multiGet(DavMultiget.Type.ADDRESS_BOOK, new String[] { "1.vcf", "2:3@my%40pc.vcf" }); // queried address book has a name assertEquals("My Book", davAddressBook.getProperties().getDisplayName()); // there are two contacts assertEquals(2, davAddressBook.getMembers().size()); // contact file names should be unescaped (yes, it's really named ...%40pc... to check double-encoding) assertEquals("1.vcf", davAddressBook.getMembers().get(0).getName()); assertEquals("2:3@my%40pc.vcf", davAddressBook.getMembers().get(1).getName()); // all contacts have some content for (WebDavResource member : davAddressBook.getMembers()) assertNotNull(member.getContent()); } public void testMultiGetWith404() throws Exception { WebDavResource davAddressBook = new WebDavResource(davCollection, "addressbooks/default-with-404.vcf/"); try { davAddressBook.multiGet(DavMultiget.Type.ADDRESS_BOOK, new String[] { "notexisting" }); fail(); } catch (NotFoundException e) { // addressbooks/default.vcf/notexisting doesn't exist, // so server responds with 404 which causes a NotFoundException } } public void testPutAddDontOverwrite() throws Exception { // should succeed on a non-existing file assertEquals("has-just-been-created", davNonExistingFile.put(SAMPLE_CONTENT, PutMode.ADD_DONT_OVERWRITE)); // should fail on an existing file try { davExistingFile.put(SAMPLE_CONTENT, PutMode.ADD_DONT_OVERWRITE); fail(); } catch (PreconditionFailedException ex) { } } public void testPutUpdateDontOverwrite() throws Exception { // should succeed on an existing file assertEquals("has-just-been-updated", davExistingFile.put(SAMPLE_CONTENT, PutMode.UPDATE_DONT_OVERWRITE)); // should fail on a non-existing file (resource has been deleted on server, thus server returns 412) try { davNonExistingFile.put(SAMPLE_CONTENT, PutMode.UPDATE_DONT_OVERWRITE); fail(); } catch (PreconditionFailedException ex) { } // should fail on existing file with wrong ETag (resource has changed on server, thus server returns 409) try { WebDavResource dav = new WebDavResource(davCollection, new URI("collection/existing.file?conflict=1")); dav.put(SAMPLE_CONTENT, PutMode.UPDATE_DONT_OVERWRITE); fail(); } catch (ConflictException ex) { } } public void testDelete() throws Exception { // should succeed on an existing file davExistingFile.delete(); // should fail on a non-existing file try { davNonExistingFile.delete(); fail(); } catch (NotFoundException e) { } } /* test CalDAV/CardDAV */ /* special test */ public void testGetSpecialURLs() throws Exception { WebDavResource dav = new WebDavResource(davAssets, "member-with:colon.vcf"); try { dav.get("*/*"); fail(); } catch (NotFoundException e) { assertTrue(true); } } }