UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2020 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "xml.h" 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 34 #include <libxml/tree.h> 35 36 #include "testutils.h" 37 38 #include "../public/webdav.h" 39 #include "../util/writer.h" 40 41 #include "../webdav/webdav.h" 42 #include "../webdav/xml.h" 43 44 typedef struct Test1Data { 45 int beginCounter; 46 int endCounter; 47 int elmCounter; 48 int endElmCounter; 49 int textErr; 50 int err; 51 int endErr; 52 int nodesWithAttributesCounter; 53 xmlNode *prev; 54 } Test1Data; 55 56 static int test1_begin(xmlNode *node, void *userdata) { 57 Test1Data *data = userdata; 58 data->beginCounter++; 59 60 if(node->type == XML_ELEMENT_NODE) { 61 data->elmCounter++; 62 const char *name = (const char*)node->name; 63 64 if(!strcmp(name, "ignore") || !strcmp(name, "ignore")) { 65 data->err = 1; 66 return 1; 67 } 68 69 switch(data->elmCounter) { 70 case 1: if(strcmp(name, "test")){ data->err = 1; return 1; } break; 71 case 2: if(strcmp(name, "elm1")) { data->err = 1; return 1; } break; 72 case 3: if(strcmp(name, "elm2")) { data->err = 1; return 1; } break; 73 case 4: if(strcmp(name, "c")) { data->err = 1; return 1; } break; 74 case 5: if(strcmp(name, "a")) { data->err = 1; return 1; } break; 75 case 6: if(strcmp(name, "d")) { data->err = 1; return 1; } break; 76 case 7: if(strcmp(name, "e")) { data->err = 1; return 1; } break; 77 case 8: if(strcmp(name, "b")) { data->err = 1; return 1; } break; 78 case 9: if(strcmp(name, "x")) { data->err = 1; return 1; } break; 79 case 10: if(strcmp(name, "z")) { data->err = 1; return 1; } break; 80 case 11: if(strcmp(name, "nextelm")) { data->err = 1; return 1; } break; 81 } 82 } else if(node->type == XML_TEXT_NODE) { 83 const char *text = (const char*)node->content; 84 if(!strcmp(text, "teststr")) { 85 if(strcmp((const char*)data->prev->name, "elm1")) { 86 data->textErr = 1; 87 return 1; 88 } 89 } else if(!strcmp(text, "hello") || !strcmp(text, "world")) { 90 if(strcmp((const char*)data->prev->name, "a")) { 91 data->textErr = 1; 92 return 1; 93 } 94 } 95 } 96 97 if(node->type == XML_ELEMENT_NODE) { 98 data->prev = node; 99 } 100 return 0; 101 } 102 103 static int test1_end(xmlNode *node, void *userdata) { 104 Test1Data *data = userdata; 105 data->endCounter++; 106 107 if(node->type == XML_ELEMENT_NODE) { 108 data->endElmCounter++; 109 const char *name = (const char*)node->name; 110 111 if(!strcmp(name, "ignore") || !strcmp(name, "ignore")) { 112 data->err = 1; 113 return 1; 114 } 115 116 switch(data->endElmCounter) { 117 case 1: if(strcmp(name, "elm1")){ data->endErr = 1; return 1; } break; 118 case 2: if(strcmp(name, "elm2")){ data->endErr = 1; return 1; } break; 119 case 3: if(strcmp(name, "a")){ data->endErr = 1; return 1; } break; 120 case 4: if(strcmp(name, "b")){ data->endErr = 1; return 1; } break; 121 case 5: if(strcmp(name, "e")){ data->endErr = 1; return 1; } break; 122 case 6: if(strcmp(name, "d")){ data->endErr = 1; return 1; } break; 123 case 7: if(strcmp(name, "c")){ data->endErr = 1; return 1; } break; 124 case 8: if(strcmp(name, "z")){ data->endErr = 1; return 1; } break; 125 case 9: if(strcmp(name, "x")){ data->endErr = 1; return 1; } break; 126 case 10: if(strcmp(name, "test")){ data->endErr = 1; return 1; } break; 127 case 11: if(strcmp(name, "nextelm")) { data->endErr = 1; return 1; } break; 128 } 129 } 130 131 return 0; 132 } 133 134 static int test2_begin(xmlNode *node, void *userdata) { 135 Test1Data *data = userdata; 136 data->beginCounter++; 137 if(node->type == XML_ELEMENT_NODE) { 138 data->elmCounter++; 139 if(node->properties) { 140 data->nodesWithAttributesCounter++; 141 } 142 } 143 return 0; 144 } 145 146 static int test2_end(xmlNode *node, void *userdata) { 147 Test1Data *data = userdata; 148 data->endCounter++; 149 if(node->type == XML_ELEMENT_NODE) { 150 data->endElmCounter++; 151 } 152 return 0; 153 } 154 155 UCX_TEST(test_wsxml_iterator) { 156 Session *sn = testutil_session(); 157 158 UCX_TEST_BEGIN; 159 160 xmlDoc *doc = xmlReadMemory( 161 XML_TESTDATA1, strlen(XML_TESTDATA1), NULL, NULL, 0); 162 xmlDoc *doc2 = xmlReadMemory( 163 XML_TESTDATA2, strlen(XML_TESTDATA2), NULL, NULL, 0); 164 xmlDoc *doc6 = xmlReadMemory( 165 XML_TESTDATA6, strlen(XML_TESTDATA6), NULL, NULL, 0); 166 UCX_TEST_ASSERT(doc, "doc is NULL"); 167 UCX_TEST_ASSERT(doc2, "doc2 is NULL"); 168 UCX_TEST_ASSERT(doc6, "doc6 is NULL"); 169 170 xmlNode *root = xmlDocGetRootElement(doc); 171 172 // Test 1: iterate over complete document 173 Test1Data testdata; 174 ZERO(&testdata, sizeof(Test1Data)); 175 int ret = wsxml_iterator(sn->pool, root, test1_begin, test1_end, &testdata); 176 UCX_TEST_ASSERT(ret == 0, "wsxml_iterator failed"); 177 UCX_TEST_ASSERT(!testdata.err, "wrong element order (begin)"); 178 UCX_TEST_ASSERT(!testdata.endErr, "wrong element order (end)"); 179 UCX_TEST_ASSERT(!testdata.textErr, "text order error"); 180 UCX_TEST_ASSERT(testdata.beginCounter == testdata.endCounter, "begin/end counter not equal"); 181 182 // Test 2: iterate over sub-document 183 ZERO(&testdata, sizeof(Test1Data)); 184 xmlNode *root2 = xmlDocGetRootElement(doc2); 185 xmlNode *sub = root2->children->children; 186 ret = wsxml_iterator(sn->pool, sub, test1_begin, test1_end, &testdata); 187 UCX_TEST_ASSERT(ret == 0, "test2: wsxml_iterator failed"); 188 UCX_TEST_ASSERT(!testdata.err, "test2: wrong element order (begin)"); 189 UCX_TEST_ASSERT(!testdata.endErr, "test2: wrong element order (end)"); 190 UCX_TEST_ASSERT(!testdata.textErr, "test2: text order error"); 191 UCX_TEST_ASSERT(testdata.beginCounter == testdata.endCounter, "test2: begin/end counter not equal"); 192 193 // Test 3: iterate over document with all kinds of node types 194 xmlNode *root6 = xmlDocGetRootElement(doc6); 195 ZERO(&testdata, sizeof(Test1Data)); 196 ret = wsxml_iterator(sn->pool, root6, test2_begin, test2_end, &testdata); 197 UCX_TEST_ASSERT(ret == 0, "test3: wsxml_iterator failed"); 198 UCX_TEST_ASSERT(testdata.elmCounter == testdata.endElmCounter, "test3: begin/end counter not equal"); 199 UCX_TEST_ASSERT(testdata.elmCounter == 12, "test3: wrong elm counter"); 200 UCX_TEST_ASSERT(testdata.nodesWithAttributesCounter == 5, "test3: wrong entity ref counter"); 201 202 xmlFreeDoc(doc); 203 xmlFreeDoc(doc2); 204 xmlFreeDoc(doc6); 205 UCX_TEST_END; 206 207 testutil_destroy_session(sn); 208 } 209 210 // checks if the namespace list contains the test namespaces x1, x2, x3 and x4 211 static void check_ns_list(WebdavNSList *list, int *x1, int *x2, int *x3, int *x4) { 212 *x1 = 0; 213 *x2 = 0; 214 *x3 = 0; 215 *x4 = 0; 216 217 WebdavNSList *elm = list; 218 while(elm) { 219 if(!strcmp((const char*)elm->namespace->prefix, "x1") && 220 !strcmp((const char*)elm->namespace->href, "http://example.com/ns1/")) 221 { 222 *x1 = 1; 223 } else if(!strcmp((const char*)elm->namespace->prefix, "x2") && 224 !strcmp((const char*)elm->namespace->href, "http://example.com/ns2/")) 225 { 226 *x2 = 1; 227 } else if(!strcmp((const char*)elm->namespace->prefix, "x3") && 228 !strcmp((const char*)elm->namespace->href, "http://example.com/ns_0/")) 229 { 230 *x3 = 1; 231 } else if(!strcmp((const char*)elm->namespace->prefix, "x4") && 232 !strcmp((const char*)elm->namespace->href, "http://example.com/ns_0/")) 233 { 234 *x4 = 1; 235 } 236 237 elm = elm->next; 238 } 239 } 240 241 UCX_TEST(test_wsxml_get_required_namespaces) { 242 Session *sn = testutil_session(); 243 244 UCX_TEST_BEGIN; 245 246 xmlDoc *doc3 = xmlReadMemory( 247 XML_TESTDATA3, strlen(XML_TESTDATA3), NULL, NULL, 0); 248 xmlDoc *doc4 = xmlReadMemory( 249 XML_TESTDATA4, strlen(XML_TESTDATA4), NULL, NULL, 0); 250 xmlDoc *doc5 = xmlReadMemory( 251 XML_TESTDATA5, strlen(XML_TESTDATA5), NULL, NULL, 0); 252 253 xmlNode *node0 = xmlDocGetRootElement(doc3); 254 xmlNode *node1 = xmlDocGetRootElement(doc3)->children; 255 xmlNode *node2 = xmlDocGetRootElement(doc4)->children; 256 xmlNode *node3 = xmlDocGetRootElement(doc5)->children; 257 258 UCX_TEST_ASSERT(doc3, "doc3 is NULL"); 259 UCX_TEST_ASSERT(doc4, "doc4 is NULL"); 260 UCX_TEST_ASSERT(doc5, "doc5 is NULL"); 261 262 int err0, err1, err2, err3; 263 int x1 = 0; 264 int x2 = 0; 265 int x3 = 0; 266 int x4 = 0; 267 WebdavNSList *elm = NULL; 268 269 // Test 0: 270 WebdavNSList *ns0 = wsxml_get_required_namespaces(sn->pool, node0, &err0); 271 UCX_TEST_ASSERT(!err0, "ns0 failed"); 272 UCX_TEST_ASSERT(!ns0, "ns0: nsdefs should be ignored"); 273 274 WebdavNSList *ns1 = wsxml_get_required_namespaces(sn->pool, node1, &err1); 275 check_ns_list(ns1, &x1, &x2, &x3, &x4); 276 UCX_TEST_ASSERT(!err1, "ns1 failed"); 277 UCX_TEST_ASSERT(ns1, "ns1: no list"); 278 UCX_TEST_ASSERT(x1, "ns1: x1 missing"); 279 UCX_TEST_ASSERT(x2, "ns1: x2 missing"); 280 UCX_TEST_ASSERT(x3, "ns1: x3 missing"); 281 UCX_TEST_ASSERT(x4, "ns1: x4 missing"); 282 283 WebdavNSList *ns2 = wsxml_get_required_namespaces(sn->pool, node2, &err2); 284 check_ns_list(ns2, &x1, &x2, &x3, &x4); 285 UCX_TEST_ASSERT(!err2, "ns2 failed"); 286 UCX_TEST_ASSERT(ns2, "ns2: no list"); 287 UCX_TEST_ASSERT(x1, "ns2: x1 missing"); 288 UCX_TEST_ASSERT(x2, "ns2: x2 missing"); 289 UCX_TEST_ASSERT(!x3, "ns2: x3"); 290 UCX_TEST_ASSERT(!x4, "ns2: x4"); 291 292 WebdavNSList *ns3 = wsxml_get_required_namespaces(sn->pool, node3, &err3); 293 check_ns_list(ns3, &x1, &x2, &x3, &x4); 294 UCX_TEST_ASSERT(!err3, "ns3 failed"); 295 UCX_TEST_ASSERT(ns3, "ns3: no list"); 296 UCX_TEST_ASSERT(x1, "ns3: x1 missing"); 297 UCX_TEST_ASSERT(x2, "ns3: x2 missing"); 298 UCX_TEST_ASSERT(!x3, "ns3: x3"); 299 UCX_TEST_ASSERT(!x4, "ns3: x4"); 300 301 xmlFreeDoc(doc3); 302 xmlFreeDoc(doc4); 303 xmlFreeDoc(doc5); 304 UCX_TEST_END; 305 306 testutil_destroy_session(sn); 307 } 308 309 UCX_TEST(test_wsxml_write_nodes) { 310 Session *sn = testutil_session(); 311 TestIOStream *st = testutil_iostream(2048, TRUE); 312 313 UCX_TEST_BEGIN; 314 xmlDoc *doc = xmlReadMemory( 315 XML_TESTDATA6, strlen(XML_TESTDATA6), NULL, NULL, 0); 316 UCX_TEST_ASSERT(doc, "xml parser error"); 317 xmlNode *root = xmlDocGetRootElement(doc); 318 319 Writer writer; 320 char buffer[1024]; 321 writer_init(&writer, st, buffer, 1024); 322 323 int err = wsxml_write_nodes(sn->pool, &writer, NULL, root); 324 writer_flush(&writer); 325 UCX_TEST_ASSERT(err == 0, "wsxml_write_nodes error"); 326 UCX_TEST_ASSERT(st->buf->pos > 0, "buffer is empty"); 327 328 //printf("\n\n"); 329 //printf("%.*s\n", (int)st->buf->size, st->buf->space); 330 //printf("\n\n"); 331 332 xmlDoc *genDoc = xmlReadMemory( 333 st->buf->space, st->buf->size, NULL, NULL, 0); 334 UCX_TEST_ASSERT(genDoc, "generated doc is not valid xml"); 335 336 xmlFreeDoc(doc); 337 xmlFreeDoc(genDoc); 338 339 UCX_TEST_END; 340 testutil_iostream_destroy(st); 341 testutil_destroy_session(sn); 342 } 343 344 UCX_TEST(test_wsxml_nslist2string) { 345 Session *sn = testutil_session(); 346 347 UCX_TEST_BEGIN; 348 349 WSNamespace ns1; 350 WSNamespace ns2; 351 WSNamespace ns3; 352 memset(&ns1, 0, sizeof(WSNamespace)); 353 memset(&ns2, 0, sizeof(WSNamespace)); 354 memset(&ns3, 0, sizeof(WSNamespace)); 355 ns1.prefix = (const xmlChar*)"x"; 356 ns1.href = (const xmlChar*)"ns1"; 357 ns2.prefix = (const xmlChar*)"y"; 358 ns2.href = (const xmlChar*)"ns2"; 359 ns3.prefix = (const xmlChar*)"z"; 360 ns3.href = (const xmlChar*)"ns3"; 361 362 WebdavNSList elm1 = { &ns1, NULL, NULL }; 363 WebdavNSList elm2 = { &ns2, NULL, NULL }; 364 WebdavNSList elm3 = { &ns3, NULL, NULL }; 365 366 // single elm test 367 char *str1 = wsxml_nslist2string(sn->pool, &elm1); 368 UCX_TEST_ASSERT(str1, "str1 is null"); 369 UCX_TEST_ASSERT(!strcmp(str1, "x:ns1"), "str1: wrong content"); 370 371 // 2 elm test 372 elm1.next = &elm2; 373 char *str2 = wsxml_nslist2string(sn->pool, &elm1); 374 UCX_TEST_ASSERT(str2, "str2 is null"); 375 UCX_TEST_ASSERT(!strcmp(str2, "x:ns1\ny:ns2"), "str2: wrong content"); 376 377 // 3 elm test 378 elm2.next = &elm3; 379 char *str3 = wsxml_nslist2string(sn->pool, &elm1); 380 UCX_TEST_ASSERT(str3, "str3 is null"); 381 UCX_TEST_ASSERT(!strcmp(str3, "x:ns1\ny:ns2\nz:ns3"), "str3: wrong content"); 382 383 // empty prefix test 384 ns1.prefix = NULL; 385 char *str4 = wsxml_nslist2string(sn->pool, &elm1); 386 UCX_TEST_ASSERT(str4, "str3 is null"); 387 UCX_TEST_ASSERT(!strcmp(str4, ":ns1\ny:ns2\nz:ns3"), "str4: wrong content"); 388 389 UCX_TEST_END; 390 testutil_destroy_session(sn); 391 } 392 393 UCX_TEST(test_wsxml_string2nslist) { 394 Session *sn = testutil_session(); 395 396 UCX_TEST_BEGIN; 397 398 // empty list 399 WebdavNSList *list1 = wsxml_string2nslist(sn->pool, ""); 400 UCX_TEST_ASSERT(!list1, "list1 should be NULL"); 401 402 // 1 elm list 403 WebdavNSList *list2 = wsxml_string2nslist(sn->pool, "x:ns1"); 404 UCX_TEST_ASSERT(list2, "list2 is NULL"); 405 UCX_TEST_ASSERT(list2->namespace, "list2 namespace is NULL"); 406 UCX_TEST_ASSERT(!strcmp((const char*)list2->namespace->prefix, "x"), "list2: wrong prefix"); 407 UCX_TEST_ASSERT(!strcmp((const char*)list2->namespace->href, "ns1"), "list2: wrong href"); 408 409 // 2 elm list 410 WebdavNSList *list3 = wsxml_string2nslist(sn->pool, "x:ns1\ny:ns2"); 411 UCX_TEST_ASSERT(list3, "list3 is NULL"); 412 UCX_TEST_ASSERT(list3->namespace, "list3 namespace is NULL"); 413 UCX_TEST_ASSERT(!strcmp((const char*)list3->namespace->prefix, "x"), "list3: wrong prefix"); 414 UCX_TEST_ASSERT(!strcmp((const char*)list3->namespace->href, "ns1"), "list3: wrong href"); 415 UCX_TEST_ASSERT(list3->next, "list3 elm2 is NULL"); 416 UCX_TEST_ASSERT(list3->next->namespace, "list3 namespace 2 is NULL"); 417 UCX_TEST_ASSERT(!strcmp((const char*)list3->namespace->prefix, "x"), "list3: elm2 wrong prefix"); 418 UCX_TEST_ASSERT(!strcmp((const char*)list3->namespace->href, "ns1"), "list3: elm2 wrong href"); 419 420 // empty prefix 421 WebdavNSList *list4 = wsxml_string2nslist(sn->pool, ":x\ny:ns2"); 422 UCX_TEST_ASSERT(list4, "list4 is NULL"); 423 UCX_TEST_ASSERT(list4->namespace, "list4 namespace is NULL"); 424 UCX_TEST_ASSERT(!list4->namespace->prefix, "list4 elm1 prefix should be NULL"); 425 UCX_TEST_ASSERT(!strcmp((const char*)list3->namespace->href, "ns1"), "list3: wrong href"); 426 427 428 UCX_TEST_END; 429 testutil_destroy_session(sn); 430 } 431