# HG changeset patch # User Olaf Wintermann # Date 1650918930 -7200 # Node ID 3ad0b65ec83838eaa0d2a3c8104a35016a7af057 # Parent f7544e220a0febc596200c7bdab72dfd4047e1ea test pg propfind response diff -r f7544e220a0f -r 3ad0b65ec838 src/server/plugins/postgresql/pgtest.c --- a/src/server/plugins/postgresql/pgtest.c Mon Apr 25 21:40:26 2022 +0200 +++ b/src/server/plugins/postgresql/pgtest.c Mon Apr 25 22:35:30 2022 +0200 @@ -46,8 +46,7 @@ #include -#include - +#define xstreq(a,b) xmlStrEqual(BAD_CAST a, BAD_CAST b) static char *pg_connstr = "postgresql://localhost/test1"; static int abort_pg_tests = 0; @@ -100,6 +99,114 @@ } } +static void parse_response_tag(TestMultistatus *ms, xmlNode *node) { + // thanks to dav for some of this code + UcxAllocator *a = ms->mp->allocator; + node = node->children; + + sstr_t href = {NULL, 0}; + UcxMap *properties = ucx_map_new_a(ms->mp->allocator, 16); + + while(node) { + if(node->type == XML_ELEMENT_NODE) { + if(xstreq(node->name, "href")) { + xmlNode *href_node = node->children; + if(href_node->type != XML_TEXT_NODE) { + return; + } + href = sstrdup_a(ms->mp->allocator, scstr((const char*)href_node->content)); + } else if(xstreq(node->name, "propstat")) { + xmlNode *n = node->children; + xmlNode *prop_node = NULL; + int status_code = 0; + while(n) { + if(n->type == XML_ELEMENT_NODE) { + if(xstreq(n->name, "prop")) { + prop_node = n; + } else if(xstreq(n->name, "status")) { + xmlNode *status_node = n->children; + if(status_node->type != XML_TEXT_NODE) { + return; + } + sstr_t status_str = sstr((char*)status_node->content); + if(status_str.length < 13) { + return; + } + status_str = sstrsubsl(status_str, 9, 3); + sstr_t status_s = sstrdup(status_str); + status_code = atoi(status_s.ptr); + free(status_s.ptr); + } + } + n = n->next; + } + + n = prop_node->children; + while(n) { + if(n->type == XML_ELEMENT_NODE) { + TestProperty *property = ucx_mempool_calloc(ms->mp, 1, sizeof(TestProperty)); + if(n->ns) { + property->prefix = n->ns->prefix ? sstrdup_a(a, scstr((const char*)n->ns->prefix)).ptr : NULL; + property->namespace = n->ns->href ? sstrdup_a(a, scstr((const char*)n->ns->href)).ptr : NULL; + } + property->name = sstrdup_a(a, scstr((const char*)n->name)).ptr; + property->node = n; + property->status = status_code; + xmlNode *value = n->children; + if(value && value->type == XML_TEXT_NODE) { + property->value = sstrdup_a(a, scstr((const char*)value->content)).ptr; + } + sstr_t pname = sstrcat(3, sstr(property->prefix), S(":"), sstr(property->name)); + ucx_map_sstr_put(properties, pname, property); + free(pname.ptr); + } + n = n->next; + } + } + } + node = node->next; + } + + TestResponse *resp =almalloc(a, sizeof(TestResponse)); + resp->href = href.ptr; + resp->properties = properties; + + ucx_map_sstr_put(ms->responses, href, resp); +} + +TestMultistatus* test_parse_multistatus(const char *space, size_t size) { + xmlDoc *doc = xmlReadMemory(space, size, NULL, NULL, 0); + if(!doc) { + return NULL; + } + + UcxMempool *mp = ucx_mempool_new(64); + TestMultistatus *ms = ucx_mempool_malloc(mp, sizeof(TestMultistatus)); + ms->doc = doc; + ms->mp = mp; + ms->responses = ucx_map_new_a(mp->allocator, 8); + + // parse response + xmlNode *xml_root = xmlDocGetRootElement(doc); + xmlNode *node = xml_root->children; + while(node) { + if(node->type == XML_ELEMENT_NODE) { + if(xstreq(node->name, "response")) { + parse_response_tag(ms, node); + } + } + node = node->next; + } + + return ms; +} + + +void test_multistatus_destroy(TestMultistatus *ms) { + +} + + UCX_TEST(test_pg_conn) { char *msg = test_connection ? PQerrorMessage(test_connection) : "no connection"; @@ -464,15 +571,25 @@ UCX_TEST_ASSERT(ret == REQ_PROCEED, "webdav_propfind (1) failed"); - xmlDoc *doc = xmlReadMemory( - st->buf->space, st->buf->size, NULL, NULL, 0); - UCX_TEST_ASSERT(doc, "propfind1: response is not valid xml"); + TestMultistatus *ms = test_parse_multistatus(st->buf->space, st->buf->size); + UCX_TEST_ASSERT(ms, "propfind1: response is not valid xml"); + + TestResponse *r1 = ucx_map_cstr_get(ms->responses, "/propfind/"); + UCX_TEST_ASSERT(r1, "propfind1: missing /propfind/ response"); + + TestProperty *p = ucx_map_cstr_get(r1->properties, "D:resourcetype"); + UCX_TEST_ASSERT(p, "propfind1: missing property 'resourcetype'"); + UCX_TEST_ASSERT(p->status == 200, "propfind1: wrong status code for property 'resourcetype'"); + + p = ucx_map_cstr_get(r1->properties, "D:getlastmodified"); + UCX_TEST_ASSERT(p, "propfind1: missing property 'getlastmodified'"); + UCX_TEST_ASSERT(p->status == 200, "propfind1: wrong status code for property 'getlastmodified'"); printf("\n\n%.*s\n", (int)st->buf->size, st->buf->space); testutil_destroy_session(sn); - xmlFreeDoc(doc); + test_multistatus_destroy(ms); testutil_iostream_destroy(st); UCX_TEST_END; diff -r f7544e220a0f -r 3ad0b65ec838 src/server/plugins/postgresql/pgtest.h --- a/src/server/plugins/postgresql/pgtest.h Mon Apr 25 21:40:26 2022 +0200 +++ b/src/server/plugins/postgresql/pgtest.h Mon Apr 25 22:35:30 2022 +0200 @@ -15,11 +15,37 @@ #define PGTEST_H #include +#include +#include #ifdef __cplusplus extern "C" { #endif +typedef struct TestMultistatus { + UcxMempool *mp; + xmlDoc *doc; + UcxMap *responses; +} TestMultistatus; + +typedef struct TestResponse { + char *href; + UcxMap *properties; +} TestResponse; + +typedef struct TestProperty { + char *prefix; + char *namespace; + char *name; + char *lang; + char *value; + xmlNode *node; + int status; +} TestProperty; + +TestMultistatus* test_parse_multistatus(const char *space, size_t size); +void test_multistatus_destroy(TestMultistatus *ms); + UCX_TEST(test_pg_conn); UCX_TEST(test_pg_vfs_open); diff -r f7544e220a0f -r 3ad0b65ec838 src/server/plugins/postgresql/webdav.c --- a/src/server/plugins/postgresql/webdav.c Mon Apr 25 21:40:26 2022 +0200 +++ b/src/server/plugins/postgresql/webdav.c Mon Apr 25 22:35:30 2022 +0200 @@ -354,7 +354,7 @@ PGresult *result = pg->result; WebdavVFSProperties vfsprops = pg->vfsproperties; - WSBool vfsprops_set = 0; + WSBool vfsprops_set = 0; // are live properties added to the response? int64_t current_resource_id = pg->resource_id; for(int r=0;rnrows;r++) { // columns: @@ -380,7 +380,6 @@ return 1; } - //char *nodename = PQgetvalue(result, r, 3); if(resource_id != current_resource_id) { // create a href string for the new resource // if the resource is a collection, it should have a trailing '/' @@ -402,7 +401,7 @@ current_resource_id = resource_id; } - // standard webdav properties + // standard webdav live properties if(!vfsprops_set) { if(vfsprops.getresourcetype) { if(iscollection) { @@ -433,7 +432,6 @@ } - vfsprops_set = TRUE; } @@ -459,10 +457,8 @@ resource->addproperty(resource, property, 200); } - + } - } - return 0; }