test pg propfind response webdav

Mon, 25 Apr 2022 22:35:30 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 25 Apr 2022 22:35:30 +0200
branch
webdav
changeset 313
3ad0b65ec838
parent 312
f7544e220a0f
child 314
6b1a6066ee43

test pg propfind response

src/server/plugins/postgresql/pgtest.c file | annotate | diff | comparison | revisions
src/server/plugins/postgresql/pgtest.h file | annotate | diff | comparison | revisions
src/server/plugins/postgresql/webdav.c file | annotate | diff | comparison | revisions
--- 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 <libpq-fe.h>
 
-#include <libxml/tree.h>
-
+#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;
--- 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 <ucx/test.h>
+#include <ucx/map.h>
+#include <libxml/tree.h>
 
 #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);
--- 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;r<pg->nrows;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;
 }
 

mercurial