src/server/test/webdav.c

branch
webdav
changeset 211
2160585200ac
child 212
d7e7ea9c6bc6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/test/webdav.c	Thu Oct 31 10:26:35 2019 +0100
@@ -0,0 +1,412 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2019 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "testutils.h"
+
+#include "../webdav/requestparser.h"
+#include "../webdav/webdav.h"
+#include "../webdav/multistatus.h"
+
+#include "webdav.h"
+
+UCX_TEST(test_propfind_parse) {
+    Session *sn = testutil_session();
+    Request *rq = testutil_request(sn->pool, "PROPFIND", "/");
+    
+    UCX_TEST_BEGIN
+    
+    int error = 0;
+    
+    //
+    // ----------------- TEST_PROPFIND1 -----------------
+    // test basic propfind request
+    WebdavPropfindRequest *p1 = propfind_parse(
+            sn,
+            rq,
+            TEST_PROPFIND1,
+            strlen(TEST_PROPFIND1),
+            &error);
+    
+    UCX_TEST_ASSERT(p1, "p1 is NULL");
+    UCX_TEST_ASSERT(p1->properties, "p1: no props");
+    UCX_TEST_ASSERT(!p1->allprop, "p1: allprop is TRUE");
+    UCX_TEST_ASSERT(!p1->propname, "p1: propname is TRUE");
+    UCX_TEST_ASSERT(p1->propcount == 6, "p1: wrong propcount");
+    
+    // property 1: DAV:displayname
+    WebdavPList *elm = p1->properties;
+    UCX_TEST_ASSERT(
+            !strcmp(elm->property->name, "displayname"),
+            "p1: property 1 has wrong name");
+    UCX_TEST_ASSERT(
+            !strcmp((char*)elm->property->namespace->href, "DAV:"),
+            "p1: property 1 has wrong namespace");
+    
+    // property 2: DAV:getcontentlength
+    elm = elm->next;
+    UCX_TEST_ASSERT(elm, "p1: property 2 missing");
+    UCX_TEST_ASSERT(
+            !strcmp(elm->property->name, "getcontentlength"),
+            "p1: property 2 has wrong name");
+    UCX_TEST_ASSERT(
+            !strcmp((char*)elm->property->namespace->href, "DAV:"),
+            "p1: property 2 has wrong namespace");
+    
+    elm = elm->next;
+    UCX_TEST_ASSERT(elm, "p1: property 3 missing");
+    elm = elm->next;
+    UCX_TEST_ASSERT(elm, "p1: property 4 missing");
+    elm = elm->next;
+    UCX_TEST_ASSERT(elm, "p1: property 5 missing");
+    
+    // property 6: DAV:getetag
+    elm = elm->next;
+    UCX_TEST_ASSERT(elm, "p1: property 6 missing");
+    UCX_TEST_ASSERT(
+            !strcmp(elm->property->name, "getetag"),
+            "p1: property 6 has wrong name");
+    UCX_TEST_ASSERT(
+            !strcmp((char*)elm->property->namespace->href, "DAV:"),
+            "p1: property 6 has wrong namespace");
+    UCX_TEST_ASSERT(!elm->next, "p1: should not have property 7");
+    
+    //
+    // ----------------- TEST_PROPFIND2 -----------------
+    // test with multiple namespaces
+    WebdavPropfindRequest *p2 = propfind_parse(
+            sn,
+            rq,
+            TEST_PROPFIND2,
+            strlen(TEST_PROPFIND2),
+            &error);
+    
+    UCX_TEST_ASSERT(p2, "p2 is NULL");
+    UCX_TEST_ASSERT(p2->properties, "p2: no props");
+    UCX_TEST_ASSERT(!p2->allprop, "p2: allprop is TRUE");
+    UCX_TEST_ASSERT(!p2->propname, "p2: propname is TRUE");
+    
+    // property 1: DAV:resourcetype
+    elm = p2->properties;
+    UCX_TEST_ASSERT(
+            !strcmp(elm->property->name, "resourcetype"),
+            "p2: property 1 has wrong name");
+    UCX_TEST_ASSERT(
+            !strcmp((char*)elm->property->namespace->href, "DAV:"),
+            "p2: property 1 has wrong namespace");
+    
+    // property 2: X:testprop
+    elm = elm->next;
+    UCX_TEST_ASSERT(elm, "p2: property 2 missing");
+    UCX_TEST_ASSERT(
+            !strcmp(elm->property->name, "testprop"),
+            "p2: property 2 has wrong name");
+    UCX_TEST_ASSERT(
+            !strcmp((char*)elm->property->namespace->href, "http://example.com/"),
+            "p2: property 2 has wrong namespace");
+    
+    // property 3: X:name
+    elm = elm->next;
+    UCX_TEST_ASSERT(elm, "p2: property 3 missing");
+    UCX_TEST_ASSERT(
+            !strcmp(elm->property->name, "name"),
+            "p2: property 3 has wrong name");
+    UCX_TEST_ASSERT(
+            !strcmp((char*)elm->property->namespace->href, "http://example.com/"),
+            "p2: property 3 has wrong namespace");
+    
+    // property 4: Z:testprop
+    elm = elm->next;
+    UCX_TEST_ASSERT(elm, "p2: property 4 missing");
+    UCX_TEST_ASSERT(
+            !strcmp(elm->property->name, "testprop"),
+            "p2: property 4 has wrong name");
+    UCX_TEST_ASSERT(
+            !strcmp((char*)elm->property->namespace->href, "testns"),
+            "p2: property 4 has wrong namespace");
+    
+    
+    //
+    // ----------------- TEST_PROPFIND3 -----------------
+    // test allprop
+    WebdavPropfindRequest *p3 = propfind_parse(sn, rq, TEST_PROPFIND3, strlen(TEST_PROPFIND3), &error);
+    
+    UCX_TEST_ASSERT(p3, "p3 is NULL");
+    UCX_TEST_ASSERT(!p3->properties, "p2: has props");
+    UCX_TEST_ASSERT(p3->allprop, "p2: allprop is FALSE");
+    UCX_TEST_ASSERT(!p3->propname, "p2: propname is TRUE");
+    UCX_TEST_ASSERT(p3->propcount == 0, "p2: wrong propcount");
+    
+    
+    //
+    // ----------------- TEST_PROPFIND4 -----------------
+    // test propname
+    WebdavPropfindRequest *p4 = propfind_parse(sn, rq, TEST_PROPFIND4, strlen(TEST_PROPFIND4), &error);
+    
+    UCX_TEST_ASSERT(p4, "p4 is NULL");
+    UCX_TEST_ASSERT(!p4->properties, "p2: has props");
+    UCX_TEST_ASSERT(!p4->allprop, "p2: allprop is TRUE");
+    UCX_TEST_ASSERT(p4->propname, "p2: propname is FALSE");
+    
+    
+    //
+    // ----------------- TEST_PROPFIND5 -----------------
+    // test duplicate check
+    WebdavPropfindRequest *p5 = propfind_parse(sn, rq, TEST_PROPFIND5, strlen(TEST_PROPFIND5), &error);
+    
+    UCX_TEST_ASSERT(p5, "p5 is NULL");
+    UCX_TEST_ASSERT(p5->properties, "p5: no props");
+    UCX_TEST_ASSERT(!p5->allprop, "p5: allprop is TRUE");
+    UCX_TEST_ASSERT(!p5->propname, "p5: propname is TRUE");
+    UCX_TEST_ASSERT(p5->propcount == 4, "p5: wrong propcount");
+    
+    // property 1: DAV:displayname
+    elm = p5->properties;
+    UCX_TEST_ASSERT(elm, "p5: property 1 missing");
+    UCX_TEST_ASSERT(
+            !strcmp(elm->property->name, "displayname"),
+            "p5: property 1 has wrong name");
+    UCX_TEST_ASSERT(
+            !strcmp((char*)elm->property->namespace->href, "DAV:"),
+            "p5: property 1 has wrong namespace");
+    
+    elm = elm->next;
+    UCX_TEST_ASSERT(elm, "p5: property 2 missing");
+    elm = elm->next;
+    UCX_TEST_ASSERT(elm, "p5: property 3 missing");
+    
+    // property 4: DAV:resourcetype
+    elm = elm->next;
+    UCX_TEST_ASSERT(elm, "p5: property 4 missing");
+    UCX_TEST_ASSERT(
+            !strcmp(elm->property->name, "resourcetype"),
+            "p5: property 4 has wrong name");
+    UCX_TEST_ASSERT(
+            !strcmp((char*)elm->property->namespace->href, "DAV:"),
+            "p5: property 4 has wrong namespace");
+    
+    
+    //
+    // ----------------- TEST_PROPFIND6 -----------------
+    // test prop/allprop mix
+    WebdavPropfindRequest *p6 = propfind_parse(sn, rq, TEST_PROPFIND6, strlen(TEST_PROPFIND6), &error);
+    
+    UCX_TEST_ASSERT(p6, "p5 is NULL");
+    UCX_TEST_ASSERT(!p6->properties, "p5: has props");
+    UCX_TEST_ASSERT(p6->allprop, "p5: allprop is FALSE");
+    UCX_TEST_ASSERT(!p6->propname, "p5: propname is TRUE");
+    UCX_TEST_ASSERT(p6->propcount == 0, "p5: wrong propcount");
+    
+    UCX_TEST_END
+            
+    pool_destroy(sn->pool);
+}
+
+UCX_TEST(test_proppatch_parse) {
+    Session *sn = testutil_session();
+    Request *rq = testutil_request(sn->pool, "PROPPATCH", "/");
+    
+    UCX_TEST_BEGIN
+    int error = 0;
+    
+    WebdavProppatchRequest *p1 = proppatch_parse(sn, rq, TEST_PROPPATCH1, strlen(TEST_PROPPATCH1), &error);
+    
+    UCX_TEST_ASSERT(p1->set, "p1: missing set props");
+    UCX_TEST_ASSERT(!p1->remove, "p1: has remove props");
+    UCX_TEST_ASSERT(p1->setcount == 2, "p1: wrong setcount");
+    UCX_TEST_ASSERT(p1->set->next, "p1: set plist broken");
+    UCX_TEST_ASSERT(!p1->set->next->next, "p1: set plist has no end");
+    UCX_TEST_ASSERT(p1->set->property, "p1: missing property ptr in plist");
+    UCX_TEST_ASSERT(
+            !strcmp(p1->set->property->name, "test"),
+            "p1: wrong property 1 name");
+    
+    WebdavProppatchRequest *p2 = proppatch_parse(sn, rq, TEST_PROPPATCH2, strlen(TEST_PROPPATCH2), &error);
+    
+    UCX_TEST_ASSERT(p2->set, "p2: missing set props");
+    UCX_TEST_ASSERT(p2->remove, "p2: missing remove props");
+    UCX_TEST_ASSERT(p2->setcount == 4, "p2: wrong setcount");
+    UCX_TEST_ASSERT(p2->removecount == 1, "p2: wrong removecount");
+    
+    UCX_TEST_ASSERT(
+            !strcmp((char*)p2->set->property->namespace->href, "http://example.com/"),
+            "p2: set property 1: wrong namespace");
+    UCX_TEST_ASSERT(
+            !strcmp(p2->set->property->name, "a"),
+            "p2: set property 1: wrong name");
+    WSXmlNode *p2set1 = p2->set->property->value;
+    UCX_TEST_ASSERT(
+            p2set1->type == WS_NODE_TEXT,
+            "p2: set property 1: wrong type");
+    UCX_TEST_ASSERT(
+            p2set1->content,
+            "p2: set property 1: no text");
+    UCX_TEST_ASSERT(
+            !strcmp((char*)p2set1->content, "test"),
+            "p2: set property 1: wrong value");
+    
+    WSXmlNode *p2set3 = p2->set->next->next->property->value;
+    UCX_TEST_ASSERT(p2set3, "p2: set property 3 missing");
+    UCX_TEST_ASSERT(
+            p2set3->type == WS_NODE_TEXT,
+            "p2: set property 3: wrong type");
+    UCX_TEST_ASSERT(
+            p2set3->next,
+            "p2: set property 3: missing element X:name");
+    
+    UCX_TEST_ASSERT(
+            xmlHasProp(p2set3->next, BAD_CAST"test"),
+            "p2: set property 3: missing attribute 'test'");
+    
+    UCX_TEST_ASSERT(
+            xmlHasProp(p2set3->next, BAD_CAST"abc"),
+            "p2: set property 3: missing attribute 'abc");
+    
+    xmlChar *value1 = xmlGetProp(p2set3->next, BAD_CAST"test");
+    UCX_TEST_ASSERT(
+            !strcmp((char*) value1, "test1"),
+            "p2: set property 3: wrong attribute value 1");
+    xmlFree(value1);
+    
+    xmlChar *value2 = xmlGetProp(p2set3->next, BAD_CAST"abc");
+    UCX_TEST_ASSERT(
+            !strcmp((char*) value2, "def"),
+            "p2: set property 3: wrong attribute value 2");
+    xmlFree(value2);
+    
+    UCX_TEST_ASSERT(
+            !strcmp(p2->remove->property->name, "e"),
+            "p2: wrong remove property");
+    
+    UCX_TEST_END
+            
+    pool_destroy(sn->pool);
+}
+
+UCX_TEST(test_lock_parse) {
+    Session *sn = testutil_session();
+    Request *rq = testutil_request(sn->pool, "LOCK", "/");
+    
+    UCX_TEST_BEGIN
+    int error = 0;
+    
+    WebdavLockRequest *l1 = lock_parse(sn, rq, TEST_LOCK1, strlen(TEST_LOCK1), &error);
+    
+    UCX_TEST_ASSERT(l1, "l1 is NULL");
+    UCX_TEST_ASSERT(l1->type == WEBDAV_LOCK_WRITE, "l1: wrong type");
+    UCX_TEST_ASSERT(l1->scope == WEBDAV_LOCK_SHARED, "l1: wrong scope");
+    UCX_TEST_ASSERT(l1->owner, "l1: owner is NULL");
+    UCX_TEST_ASSERT(!strcmp((char*)l1->owner->content, "User"), "l1: wrong owner");
+    
+    UCX_TEST_END
+    
+    pool_destroy(sn->pool);
+}
+
+UCX_TEST(test_rqbody2buffer) {
+    Session *sn;
+    Request *rq;
+    
+    UCX_TEST_BEGIN;
+    //
+    // TEST 1
+    sn = testutil_session();
+    rq = testutil_request(sn->pool, "PUT", "/");
+    testutil_request_body(sn, rq, "Hello World!", 12);
+    
+    UcxBuffer *b1 = rqbody2buffer(sn, rq);
+    UCX_TEST_ASSERT(b1->size == 12, "b1: wrong size");
+    UCX_TEST_ASSERT(!memcmp(b1->space,"Hello World!",12), "b1: wrong content");
+    
+    ucx_buffer_free(b1);
+    testutil_destroy_session(sn);
+    
+    //
+    // TEST 2
+    size_t len1 = 25000;
+    unsigned char *body1 = malloc(len1);
+    for(int i=0;i<len1;i++) {
+        body1[i] = i;
+    }
+    sn = testutil_session();
+    rq = testutil_request(sn->pool, "PUT", "/");
+    testutil_request_body(sn, rq, (char*)body1, len1);
+    
+    UcxBuffer *b2 = rqbody2buffer(sn, rq);
+    UCX_TEST_ASSERT(b2->size == len1, "b2: wrong size");
+    UCX_TEST_ASSERT(!memcmp(b2->space, body1, len1), "b2: wrong content");
+    
+    ucx_buffer_free(b2);
+    testutil_destroy_session(sn);
+    
+    UCX_TEST_END;
+}
+
+UCX_TEST(test_msresponse_addproperty) {
+    Session *sn = testutil_session();
+    Request *rq = testutil_request(sn->pool, "PROPFIND", "/");
+    Multistatus *ms = multistatus_response(sn, rq);
+    MSResponse *r;
+    
+    UCX_TEST_BEGIN;
+    
+    r = (MSResponse*)ms->response.addresource((WebdavResponse*)ms, "/");
+    
+    WebdavProperty p1;
+    WebdavProperty p[16];
+    
+    UCX_TEST_ASSERT(!r->plist_begin && !r->plist_end, "plist not empty");
+    
+    r->resource.addproperty((WebdavResource*)r, &p1, 200);
+    UCX_TEST_ASSERT(r->plist_begin, "!plist_begin");
+    UCX_TEST_ASSERT(r->plist_begin == r->plist_end, "plist begin != end");
+    
+    r->resource.addproperty((WebdavResource*)r, &p[0], 404);
+    r->resource.addproperty((WebdavResource*)r, &p[1], 404);
+    r->resource.addproperty((WebdavResource*)r, &p[2], 403);
+    r->resource.addproperty((WebdavResource*)r, &p[3], 403);
+    r->resource.addproperty((WebdavResource*)r, &p[4], 403);
+    r->resource.addproperty((WebdavResource*)r, &p[5], 403);
+    r->resource.addproperty((WebdavResource*)r, &p[6], 500);
+    
+    UCX_TEST_ASSERT(r->plist_begin == r->plist_end, "plist begin != end");
+    
+    UCX_TEST_ASSERT(r->errors, "no prop errors");
+    UCX_TEST_ASSERT(r->errors->next, "no second error code");
+    UCX_TEST_ASSERT(r->errors->next->next, "no third error code");
+    UCX_TEST_ASSERT(!r->errors->next->next->next, "too many error codes");
+    
+    UCX_TEST_ASSERT(ucx_list_size(r->errors->begin) == 2, "404 list size != 2");
+    UCX_TEST_ASSERT(ucx_list_size(r->errors->next->begin) == 4, "403 list size != 4");
+    UCX_TEST_ASSERT(ucx_list_size(r->errors->next->next->begin) == 1, "500 list size != 1");
+    
+    UCX_TEST_END;
+}

mercurial