|
1 /* |
|
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
|
3 * |
|
4 * Copyright 2019 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 <stdio.h> |
|
30 #include <stdlib.h> |
|
31 #include <string.h> |
|
32 |
|
33 #include "testutils.h" |
|
34 |
|
35 #include "../webdav/requestparser.h" |
|
36 #include "../webdav/webdav.h" |
|
37 #include "../webdav/multistatus.h" |
|
38 |
|
39 #include "webdav.h" |
|
40 |
|
41 UCX_TEST(test_propfind_parse) { |
|
42 Session *sn = testutil_session(); |
|
43 Request *rq = testutil_request(sn->pool, "PROPFIND", "/"); |
|
44 |
|
45 UCX_TEST_BEGIN |
|
46 |
|
47 int error = 0; |
|
48 |
|
49 // |
|
50 // ----------------- TEST_PROPFIND1 ----------------- |
|
51 // test basic propfind request |
|
52 WebdavPropfindRequest *p1 = propfind_parse( |
|
53 sn, |
|
54 rq, |
|
55 TEST_PROPFIND1, |
|
56 strlen(TEST_PROPFIND1), |
|
57 &error); |
|
58 |
|
59 UCX_TEST_ASSERT(p1, "p1 is NULL"); |
|
60 UCX_TEST_ASSERT(p1->properties, "p1: no props"); |
|
61 UCX_TEST_ASSERT(!p1->allprop, "p1: allprop is TRUE"); |
|
62 UCX_TEST_ASSERT(!p1->propname, "p1: propname is TRUE"); |
|
63 UCX_TEST_ASSERT(p1->propcount == 6, "p1: wrong propcount"); |
|
64 |
|
65 // property 1: DAV:displayname |
|
66 WebdavPList *elm = p1->properties; |
|
67 UCX_TEST_ASSERT( |
|
68 !strcmp(elm->property->name, "displayname"), |
|
69 "p1: property 1 has wrong name"); |
|
70 UCX_TEST_ASSERT( |
|
71 !strcmp((char*)elm->property->namespace->href, "DAV:"), |
|
72 "p1: property 1 has wrong namespace"); |
|
73 |
|
74 // property 2: DAV:getcontentlength |
|
75 elm = elm->next; |
|
76 UCX_TEST_ASSERT(elm, "p1: property 2 missing"); |
|
77 UCX_TEST_ASSERT( |
|
78 !strcmp(elm->property->name, "getcontentlength"), |
|
79 "p1: property 2 has wrong name"); |
|
80 UCX_TEST_ASSERT( |
|
81 !strcmp((char*)elm->property->namespace->href, "DAV:"), |
|
82 "p1: property 2 has wrong namespace"); |
|
83 |
|
84 elm = elm->next; |
|
85 UCX_TEST_ASSERT(elm, "p1: property 3 missing"); |
|
86 elm = elm->next; |
|
87 UCX_TEST_ASSERT(elm, "p1: property 4 missing"); |
|
88 elm = elm->next; |
|
89 UCX_TEST_ASSERT(elm, "p1: property 5 missing"); |
|
90 |
|
91 // property 6: DAV:getetag |
|
92 elm = elm->next; |
|
93 UCX_TEST_ASSERT(elm, "p1: property 6 missing"); |
|
94 UCX_TEST_ASSERT( |
|
95 !strcmp(elm->property->name, "getetag"), |
|
96 "p1: property 6 has wrong name"); |
|
97 UCX_TEST_ASSERT( |
|
98 !strcmp((char*)elm->property->namespace->href, "DAV:"), |
|
99 "p1: property 6 has wrong namespace"); |
|
100 UCX_TEST_ASSERT(!elm->next, "p1: should not have property 7"); |
|
101 |
|
102 // |
|
103 // ----------------- TEST_PROPFIND2 ----------------- |
|
104 // test with multiple namespaces |
|
105 WebdavPropfindRequest *p2 = propfind_parse( |
|
106 sn, |
|
107 rq, |
|
108 TEST_PROPFIND2, |
|
109 strlen(TEST_PROPFIND2), |
|
110 &error); |
|
111 |
|
112 UCX_TEST_ASSERT(p2, "p2 is NULL"); |
|
113 UCX_TEST_ASSERT(p2->properties, "p2: no props"); |
|
114 UCX_TEST_ASSERT(!p2->allprop, "p2: allprop is TRUE"); |
|
115 UCX_TEST_ASSERT(!p2->propname, "p2: propname is TRUE"); |
|
116 |
|
117 // property 1: DAV:resourcetype |
|
118 elm = p2->properties; |
|
119 UCX_TEST_ASSERT( |
|
120 !strcmp(elm->property->name, "resourcetype"), |
|
121 "p2: property 1 has wrong name"); |
|
122 UCX_TEST_ASSERT( |
|
123 !strcmp((char*)elm->property->namespace->href, "DAV:"), |
|
124 "p2: property 1 has wrong namespace"); |
|
125 |
|
126 // property 2: X:testprop |
|
127 elm = elm->next; |
|
128 UCX_TEST_ASSERT(elm, "p2: property 2 missing"); |
|
129 UCX_TEST_ASSERT( |
|
130 !strcmp(elm->property->name, "testprop"), |
|
131 "p2: property 2 has wrong name"); |
|
132 UCX_TEST_ASSERT( |
|
133 !strcmp((char*)elm->property->namespace->href, "http://example.com/"), |
|
134 "p2: property 2 has wrong namespace"); |
|
135 |
|
136 // property 3: X:name |
|
137 elm = elm->next; |
|
138 UCX_TEST_ASSERT(elm, "p2: property 3 missing"); |
|
139 UCX_TEST_ASSERT( |
|
140 !strcmp(elm->property->name, "name"), |
|
141 "p2: property 3 has wrong name"); |
|
142 UCX_TEST_ASSERT( |
|
143 !strcmp((char*)elm->property->namespace->href, "http://example.com/"), |
|
144 "p2: property 3 has wrong namespace"); |
|
145 |
|
146 // property 4: Z:testprop |
|
147 elm = elm->next; |
|
148 UCX_TEST_ASSERT(elm, "p2: property 4 missing"); |
|
149 UCX_TEST_ASSERT( |
|
150 !strcmp(elm->property->name, "testprop"), |
|
151 "p2: property 4 has wrong name"); |
|
152 UCX_TEST_ASSERT( |
|
153 !strcmp((char*)elm->property->namespace->href, "testns"), |
|
154 "p2: property 4 has wrong namespace"); |
|
155 |
|
156 |
|
157 // |
|
158 // ----------------- TEST_PROPFIND3 ----------------- |
|
159 // test allprop |
|
160 WebdavPropfindRequest *p3 = propfind_parse(sn, rq, TEST_PROPFIND3, strlen(TEST_PROPFIND3), &error); |
|
161 |
|
162 UCX_TEST_ASSERT(p3, "p3 is NULL"); |
|
163 UCX_TEST_ASSERT(!p3->properties, "p2: has props"); |
|
164 UCX_TEST_ASSERT(p3->allprop, "p2: allprop is FALSE"); |
|
165 UCX_TEST_ASSERT(!p3->propname, "p2: propname is TRUE"); |
|
166 UCX_TEST_ASSERT(p3->propcount == 0, "p2: wrong propcount"); |
|
167 |
|
168 |
|
169 // |
|
170 // ----------------- TEST_PROPFIND4 ----------------- |
|
171 // test propname |
|
172 WebdavPropfindRequest *p4 = propfind_parse(sn, rq, TEST_PROPFIND4, strlen(TEST_PROPFIND4), &error); |
|
173 |
|
174 UCX_TEST_ASSERT(p4, "p4 is NULL"); |
|
175 UCX_TEST_ASSERT(!p4->properties, "p2: has props"); |
|
176 UCX_TEST_ASSERT(!p4->allprop, "p2: allprop is TRUE"); |
|
177 UCX_TEST_ASSERT(p4->propname, "p2: propname is FALSE"); |
|
178 |
|
179 |
|
180 // |
|
181 // ----------------- TEST_PROPFIND5 ----------------- |
|
182 // test duplicate check |
|
183 WebdavPropfindRequest *p5 = propfind_parse(sn, rq, TEST_PROPFIND5, strlen(TEST_PROPFIND5), &error); |
|
184 |
|
185 UCX_TEST_ASSERT(p5, "p5 is NULL"); |
|
186 UCX_TEST_ASSERT(p5->properties, "p5: no props"); |
|
187 UCX_TEST_ASSERT(!p5->allprop, "p5: allprop is TRUE"); |
|
188 UCX_TEST_ASSERT(!p5->propname, "p5: propname is TRUE"); |
|
189 UCX_TEST_ASSERT(p5->propcount == 4, "p5: wrong propcount"); |
|
190 |
|
191 // property 1: DAV:displayname |
|
192 elm = p5->properties; |
|
193 UCX_TEST_ASSERT(elm, "p5: property 1 missing"); |
|
194 UCX_TEST_ASSERT( |
|
195 !strcmp(elm->property->name, "displayname"), |
|
196 "p5: property 1 has wrong name"); |
|
197 UCX_TEST_ASSERT( |
|
198 !strcmp((char*)elm->property->namespace->href, "DAV:"), |
|
199 "p5: property 1 has wrong namespace"); |
|
200 |
|
201 elm = elm->next; |
|
202 UCX_TEST_ASSERT(elm, "p5: property 2 missing"); |
|
203 elm = elm->next; |
|
204 UCX_TEST_ASSERT(elm, "p5: property 3 missing"); |
|
205 |
|
206 // property 4: DAV:resourcetype |
|
207 elm = elm->next; |
|
208 UCX_TEST_ASSERT(elm, "p5: property 4 missing"); |
|
209 UCX_TEST_ASSERT( |
|
210 !strcmp(elm->property->name, "resourcetype"), |
|
211 "p5: property 4 has wrong name"); |
|
212 UCX_TEST_ASSERT( |
|
213 !strcmp((char*)elm->property->namespace->href, "DAV:"), |
|
214 "p5: property 4 has wrong namespace"); |
|
215 |
|
216 |
|
217 // |
|
218 // ----------------- TEST_PROPFIND6 ----------------- |
|
219 // test prop/allprop mix |
|
220 WebdavPropfindRequest *p6 = propfind_parse(sn, rq, TEST_PROPFIND6, strlen(TEST_PROPFIND6), &error); |
|
221 |
|
222 UCX_TEST_ASSERT(p6, "p5 is NULL"); |
|
223 UCX_TEST_ASSERT(!p6->properties, "p5: has props"); |
|
224 UCX_TEST_ASSERT(p6->allprop, "p5: allprop is FALSE"); |
|
225 UCX_TEST_ASSERT(!p6->propname, "p5: propname is TRUE"); |
|
226 UCX_TEST_ASSERT(p6->propcount == 0, "p5: wrong propcount"); |
|
227 |
|
228 UCX_TEST_END |
|
229 |
|
230 pool_destroy(sn->pool); |
|
231 } |
|
232 |
|
233 UCX_TEST(test_proppatch_parse) { |
|
234 Session *sn = testutil_session(); |
|
235 Request *rq = testutil_request(sn->pool, "PROPPATCH", "/"); |
|
236 |
|
237 UCX_TEST_BEGIN |
|
238 int error = 0; |
|
239 |
|
240 WebdavProppatchRequest *p1 = proppatch_parse(sn, rq, TEST_PROPPATCH1, strlen(TEST_PROPPATCH1), &error); |
|
241 |
|
242 UCX_TEST_ASSERT(p1->set, "p1: missing set props"); |
|
243 UCX_TEST_ASSERT(!p1->remove, "p1: has remove props"); |
|
244 UCX_TEST_ASSERT(p1->setcount == 2, "p1: wrong setcount"); |
|
245 UCX_TEST_ASSERT(p1->set->next, "p1: set plist broken"); |
|
246 UCX_TEST_ASSERT(!p1->set->next->next, "p1: set plist has no end"); |
|
247 UCX_TEST_ASSERT(p1->set->property, "p1: missing property ptr in plist"); |
|
248 UCX_TEST_ASSERT( |
|
249 !strcmp(p1->set->property->name, "test"), |
|
250 "p1: wrong property 1 name"); |
|
251 |
|
252 WebdavProppatchRequest *p2 = proppatch_parse(sn, rq, TEST_PROPPATCH2, strlen(TEST_PROPPATCH2), &error); |
|
253 |
|
254 UCX_TEST_ASSERT(p2->set, "p2: missing set props"); |
|
255 UCX_TEST_ASSERT(p2->remove, "p2: missing remove props"); |
|
256 UCX_TEST_ASSERT(p2->setcount == 4, "p2: wrong setcount"); |
|
257 UCX_TEST_ASSERT(p2->removecount == 1, "p2: wrong removecount"); |
|
258 |
|
259 UCX_TEST_ASSERT( |
|
260 !strcmp((char*)p2->set->property->namespace->href, "http://example.com/"), |
|
261 "p2: set property 1: wrong namespace"); |
|
262 UCX_TEST_ASSERT( |
|
263 !strcmp(p2->set->property->name, "a"), |
|
264 "p2: set property 1: wrong name"); |
|
265 WSXmlNode *p2set1 = p2->set->property->value; |
|
266 UCX_TEST_ASSERT( |
|
267 p2set1->type == WS_NODE_TEXT, |
|
268 "p2: set property 1: wrong type"); |
|
269 UCX_TEST_ASSERT( |
|
270 p2set1->content, |
|
271 "p2: set property 1: no text"); |
|
272 UCX_TEST_ASSERT( |
|
273 !strcmp((char*)p2set1->content, "test"), |
|
274 "p2: set property 1: wrong value"); |
|
275 |
|
276 WSXmlNode *p2set3 = p2->set->next->next->property->value; |
|
277 UCX_TEST_ASSERT(p2set3, "p2: set property 3 missing"); |
|
278 UCX_TEST_ASSERT( |
|
279 p2set3->type == WS_NODE_TEXT, |
|
280 "p2: set property 3: wrong type"); |
|
281 UCX_TEST_ASSERT( |
|
282 p2set3->next, |
|
283 "p2: set property 3: missing element X:name"); |
|
284 |
|
285 UCX_TEST_ASSERT( |
|
286 xmlHasProp(p2set3->next, BAD_CAST"test"), |
|
287 "p2: set property 3: missing attribute 'test'"); |
|
288 |
|
289 UCX_TEST_ASSERT( |
|
290 xmlHasProp(p2set3->next, BAD_CAST"abc"), |
|
291 "p2: set property 3: missing attribute 'abc"); |
|
292 |
|
293 xmlChar *value1 = xmlGetProp(p2set3->next, BAD_CAST"test"); |
|
294 UCX_TEST_ASSERT( |
|
295 !strcmp((char*) value1, "test1"), |
|
296 "p2: set property 3: wrong attribute value 1"); |
|
297 xmlFree(value1); |
|
298 |
|
299 xmlChar *value2 = xmlGetProp(p2set3->next, BAD_CAST"abc"); |
|
300 UCX_TEST_ASSERT( |
|
301 !strcmp((char*) value2, "def"), |
|
302 "p2: set property 3: wrong attribute value 2"); |
|
303 xmlFree(value2); |
|
304 |
|
305 UCX_TEST_ASSERT( |
|
306 !strcmp(p2->remove->property->name, "e"), |
|
307 "p2: wrong remove property"); |
|
308 |
|
309 UCX_TEST_END |
|
310 |
|
311 pool_destroy(sn->pool); |
|
312 } |
|
313 |
|
314 UCX_TEST(test_lock_parse) { |
|
315 Session *sn = testutil_session(); |
|
316 Request *rq = testutil_request(sn->pool, "LOCK", "/"); |
|
317 |
|
318 UCX_TEST_BEGIN |
|
319 int error = 0; |
|
320 |
|
321 WebdavLockRequest *l1 = lock_parse(sn, rq, TEST_LOCK1, strlen(TEST_LOCK1), &error); |
|
322 |
|
323 UCX_TEST_ASSERT(l1, "l1 is NULL"); |
|
324 UCX_TEST_ASSERT(l1->type == WEBDAV_LOCK_WRITE, "l1: wrong type"); |
|
325 UCX_TEST_ASSERT(l1->scope == WEBDAV_LOCK_SHARED, "l1: wrong scope"); |
|
326 UCX_TEST_ASSERT(l1->owner, "l1: owner is NULL"); |
|
327 UCX_TEST_ASSERT(!strcmp((char*)l1->owner->content, "User"), "l1: wrong owner"); |
|
328 |
|
329 UCX_TEST_END |
|
330 |
|
331 pool_destroy(sn->pool); |
|
332 } |
|
333 |
|
334 UCX_TEST(test_rqbody2buffer) { |
|
335 Session *sn; |
|
336 Request *rq; |
|
337 |
|
338 UCX_TEST_BEGIN; |
|
339 // |
|
340 // TEST 1 |
|
341 sn = testutil_session(); |
|
342 rq = testutil_request(sn->pool, "PUT", "/"); |
|
343 testutil_request_body(sn, rq, "Hello World!", 12); |
|
344 |
|
345 UcxBuffer *b1 = rqbody2buffer(sn, rq); |
|
346 UCX_TEST_ASSERT(b1->size == 12, "b1: wrong size"); |
|
347 UCX_TEST_ASSERT(!memcmp(b1->space,"Hello World!",12), "b1: wrong content"); |
|
348 |
|
349 ucx_buffer_free(b1); |
|
350 testutil_destroy_session(sn); |
|
351 |
|
352 // |
|
353 // TEST 2 |
|
354 size_t len1 = 25000; |
|
355 unsigned char *body1 = malloc(len1); |
|
356 for(int i=0;i<len1;i++) { |
|
357 body1[i] = i; |
|
358 } |
|
359 sn = testutil_session(); |
|
360 rq = testutil_request(sn->pool, "PUT", "/"); |
|
361 testutil_request_body(sn, rq, (char*)body1, len1); |
|
362 |
|
363 UcxBuffer *b2 = rqbody2buffer(sn, rq); |
|
364 UCX_TEST_ASSERT(b2->size == len1, "b2: wrong size"); |
|
365 UCX_TEST_ASSERT(!memcmp(b2->space, body1, len1), "b2: wrong content"); |
|
366 |
|
367 ucx_buffer_free(b2); |
|
368 testutil_destroy_session(sn); |
|
369 |
|
370 UCX_TEST_END; |
|
371 } |
|
372 |
|
373 UCX_TEST(test_msresponse_addproperty) { |
|
374 Session *sn = testutil_session(); |
|
375 Request *rq = testutil_request(sn->pool, "PROPFIND", "/"); |
|
376 Multistatus *ms = multistatus_response(sn, rq); |
|
377 MSResponse *r; |
|
378 |
|
379 UCX_TEST_BEGIN; |
|
380 |
|
381 r = (MSResponse*)ms->response.addresource((WebdavResponse*)ms, "/"); |
|
382 |
|
383 WebdavProperty p1; |
|
384 WebdavProperty p[16]; |
|
385 |
|
386 UCX_TEST_ASSERT(!r->plist_begin && !r->plist_end, "plist not empty"); |
|
387 |
|
388 r->resource.addproperty((WebdavResource*)r, &p1, 200); |
|
389 UCX_TEST_ASSERT(r->plist_begin, "!plist_begin"); |
|
390 UCX_TEST_ASSERT(r->plist_begin == r->plist_end, "plist begin != end"); |
|
391 |
|
392 r->resource.addproperty((WebdavResource*)r, &p[0], 404); |
|
393 r->resource.addproperty((WebdavResource*)r, &p[1], 404); |
|
394 r->resource.addproperty((WebdavResource*)r, &p[2], 403); |
|
395 r->resource.addproperty((WebdavResource*)r, &p[3], 403); |
|
396 r->resource.addproperty((WebdavResource*)r, &p[4], 403); |
|
397 r->resource.addproperty((WebdavResource*)r, &p[5], 403); |
|
398 r->resource.addproperty((WebdavResource*)r, &p[6], 500); |
|
399 |
|
400 UCX_TEST_ASSERT(r->plist_begin == r->plist_end, "plist begin != end"); |
|
401 |
|
402 UCX_TEST_ASSERT(r->errors, "no prop errors"); |
|
403 UCX_TEST_ASSERT(r->errors->next, "no second error code"); |
|
404 UCX_TEST_ASSERT(r->errors->next->next, "no third error code"); |
|
405 UCX_TEST_ASSERT(!r->errors->next->next->next, "too many error codes"); |
|
406 |
|
407 UCX_TEST_ASSERT(ucx_list_size(r->errors->begin) == 2, "404 list size != 2"); |
|
408 UCX_TEST_ASSERT(ucx_list_size(r->errors->next->begin) == 4, "403 list size != 4"); |
|
409 UCX_TEST_ASSERT(ucx_list_size(r->errors->next->next->begin) == 1, "500 list size != 1"); |
|
410 |
|
411 UCX_TEST_END; |
|
412 } |