at.bitfire.davdroid.webdav.WebDavResourceTest.java Source code

Java tutorial

Introduction

Here is the source code for at.bitfire.davdroid.webdav.WebDavResourceTest.java

Source

/*
 * 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);
        }
    }

}