diff -r 21274e5950af -r 2160585200ac src/server/test/webdav.c --- /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 +#include +#include + +#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;ipool, "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; +}