xref: /netbsd-src/external/mpl/dhcp/dist/common/tests/test_alloc.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: test_alloc.c,v 1.2 2018/04/07 22:37:29 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 2007-2017 by Internet Systems Consortium, Inc. ("ISC")
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 /*
19  * We test the functions provided in alloc.c here. These are very
20  * basic functions, and it is very important that they work correctly.
21  *
22  * You can see two different styles of testing:
23  *
24  * - In the first, we have a single test for each function that tests
25  *   all of the possible ways it can operate. (This is the case for
26  *   the buffer tests.)
27  *
28  * - In the second, we have a separate test for each of the ways a
29  *   function can operate. (This is the case for the data_string
30  *   tests.)
31  *
32  * The advantage of a single test per function is that you have fewer
33  * tests, and less duplicated and extra code. The advantage of having
34  * a separate test is that each test is simpler. Plus if you need to
35  * allow certain tests to fail for some reason (known bugs that are
36  * hard to fix for example), then
37  */
38 
39 /** @TODO: dmalloc() test */
40 
41 #include "config.h"
42 #include <atf-c.h>
43 #include "dhcpd.h"
44 #include "omapip/alloc.h"
45 
46 static const char* checkString (struct data_string* ds, const char *src);
47 
48 ATF_TC(buffer_allocate);
49 
50 ATF_TC_HEAD(buffer_allocate, tc) {
51     atf_tc_set_md_var(tc, "descr", "buffer_allocate basic test");
52 }
53 
54 ATF_TC_BODY(buffer_allocate, tc) {
55     struct buffer *buf = 0;
56 
57     /*
58      * Check a 0-length buffer.
59      */
60     buf = NULL;
61     if (!buffer_allocate(&buf, 0, MDL)) {
62         atf_tc_fail("failed on 0-len buffer");
63     }
64     if (!buffer_dereference(&buf, MDL)) {
65         atf_tc_fail("buffer_dereference() failed");
66     }
67     if (buf != NULL) {
68         atf_tc_fail("buffer_dereference() did not NULL-out buffer");
69     }
70 
71     /*
72      * Check an actual buffer.
73      */
74     buf = NULL;
75     if (!buffer_allocate(&buf, 100, MDL)) {
76         atf_tc_fail("failed on allocate 100 bytes\n");
77     }
78     if (!buffer_dereference(&buf, MDL)) {
79         atf_tc_fail("buffer_dereference() failed");
80     }
81     if (buf != NULL) {
82         atf_tc_fail("buffer_dereference() did not NULL-out buffer");
83     }
84 
85     /*
86      * Okay, we're happy.
87      */
88     atf_tc_pass();
89 }
90 
91 ATF_TC(buffer_reference);
92 
93 ATF_TC_HEAD(buffer_reference, tc) {
94     atf_tc_set_md_var(tc, "descr", "buffer_reference basic test");
95 }
96 
97 ATF_TC_BODY(buffer_reference, tc) {
98 
99     struct buffer *a, *b;
100 
101     /*
102      * Create a buffer.
103      */
104     a = NULL;
105     if (!buffer_allocate(&a, 100, MDL)) {
106         atf_tc_fail("failed on allocate 100 bytes");
107     }
108 
109     /**
110      * Confirm buffer_reference() doesn't work if we pass in NULL.
111      *
112      * @TODO: we should confirm we get an error message here.
113      */
114     if (buffer_reference(NULL, a, MDL)) {
115         atf_tc_fail("succeeded on an error input");
116     }
117 
118     /**
119      * @TODO: we should confirm we get an error message if we pass
120      *       a non-NULL target.
121      */
122 
123     /*
124      * Confirm we work under normal circumstances.
125      */
126     b = NULL;
127     if (!buffer_reference(&b, a, MDL)) {
128         atf_tc_fail("buffer_reference() failed");
129     }
130 
131     if (b != a) {
132         atf_tc_fail("incorrect pointer returned");
133     }
134 
135     if (b->refcnt != 2) {
136         atf_tc_fail("incorrect refcnt");
137     }
138 
139     /*
140      * Clean up.
141      */
142     if (!buffer_dereference(&b, MDL)) {
143         atf_tc_fail("buffer_dereference() failed");
144     }
145     if (!buffer_dereference(&a, MDL)) {
146         atf_tc_fail("buffer_dereference() failed");
147     }
148 
149 }
150 
151 
152 ATF_TC(buffer_dereference);
153 
154 ATF_TC_HEAD(buffer_dereference, tc) {
155     atf_tc_set_md_var(tc, "descr", "buffer_dereference basic test");
156 }
157 
158 ATF_TC_BODY(buffer_dereference, tc) {
159     struct buffer *a, *b;
160 
161     /**
162      * Confirm buffer_dereference() doesn't work if we pass in NULL.
163      *
164      * TODO: we should confirm we get an error message here.
165      */
166     if (buffer_dereference(NULL, MDL)) {
167         atf_tc_fail("succeeded on an error input");
168     }
169 
170     /**
171      * Confirm buffer_dereference() doesn't work if we pass in
172      * a pointer to NULL.
173      *
174      * @TODO: we should confirm we get an error message here.
175      */
176     a = NULL;
177     if (buffer_dereference(&a, MDL)) {
178         atf_tc_fail("succeeded on an error input");
179     }
180 
181     /*
182      * Confirm we work under normal circumstances.
183      */
184     a = NULL;
185     if (!buffer_allocate(&a, 100, MDL)) {
186         atf_tc_fail("failed on allocate");
187     }
188     if (!buffer_dereference(&a, MDL)) {
189         atf_tc_fail("buffer_dereference() failed");
190     }
191     if (a != NULL) {
192         atf_tc_fail("non-null buffer after buffer_dereference()");
193     }
194 
195     /**
196      * Confirm we get an error from negative refcnt.
197      *
198      * @TODO: we should confirm we get an error message here.
199      */
200     a = NULL;
201     if (!buffer_allocate(&a, 100, MDL)) {
202         atf_tc_fail("failed on allocate");
203     }
204     b = NULL;
205     if (!buffer_reference(&b, a, MDL)) {
206         atf_tc_fail("buffer_reference() failed");
207     }
208     a->refcnt = 0;    /* purposely set to invalid value */
209     if (buffer_dereference(&a, MDL)) {
210         atf_tc_fail("buffer_dereference() succeeded on error input");
211     }
212     a->refcnt = 2;
213     if (!buffer_dereference(&b, MDL)) {
214         atf_tc_fail("buffer_dereference() failed");
215     }
216     if (!buffer_dereference(&a, MDL)) {
217         atf_tc_fail("buffer_dereference() failed");
218     }
219 }
220 
221 ATF_TC(data_string_forget);
222 
223 ATF_TC_HEAD(data_string_forget, tc) {
224     atf_tc_set_md_var(tc, "descr", "data_string_forget basic test");
225 }
226 
227 ATF_TC_BODY(data_string_forget, tc) {
228     struct buffer *buf;
229     struct data_string a;
230     const char *str = "Lorem ipsum dolor sit amet turpis duis.";
231 
232     /*
233      * Create the string we want to forget.
234      */
235     memset(&a, 0, sizeof(a));
236     a.len = strlen(str);
237     buf = NULL;
238     if (!buffer_allocate(&buf, a.len, MDL)) {
239         atf_tc_fail("out of memory");
240     }
241     if (!buffer_reference(&a.buffer, buf, MDL)) {
242         atf_tc_fail("buffer_reference() failed");
243     }
244     a.data = a.buffer->data;
245     memcpy(a.buffer->data, str, a.len);
246 
247     /*
248      * Forget and confirm we've forgotten.
249      */
250     data_string_forget(&a, MDL);
251 
252     if (a.len != 0) {
253         atf_tc_fail("incorrect length");
254     }
255 
256     if (a.data != NULL) {
257         atf_tc_fail("incorrect data");
258     }
259     if (a.terminated) {
260         atf_tc_fail("incorrect terminated");
261     }
262     if (a.buffer != NULL) {
263         atf_tc_fail("incorrect buffer");
264     }
265     if (buf->refcnt != 1) {
266         atf_tc_fail("too many references to buf");
267     }
268 
269     /*
270      * Clean up buffer.
271      */
272     if (!buffer_dereference(&buf, MDL)) {
273         atf_tc_fail("buffer_reference() failed");
274     }
275 }
276 
277 ATF_TC(data_string_forget_nobuf);
278 
279 ATF_TC_HEAD(data_string_forget_nobuf, tc) {
280     atf_tc_set_md_var(tc, "descr", "data_string_forget test, "
281                       "data_string without buffer");
282 }
283 
284 ATF_TC_BODY(data_string_forget_nobuf, tc) {
285     struct data_string a;
286     const char *str = "Lorem ipsum dolor sit amet massa nunc.";
287 
288     /*
289      * Create the string we want to forget.
290      */
291     memset(&a, 0, sizeof(a));
292     a.len = strlen(str);
293     a.data = (const unsigned char *)str;
294     a.terminated = 1;
295 
296     /*
297      * Forget and confirm we've forgotten.
298      */
299     data_string_forget(&a, MDL);
300 
301     if (a.len != 0) {
302         atf_tc_fail("incorrect length");
303     }
304     if (a.data != NULL) {
305         atf_tc_fail("incorrect data");
306     }
307     if (a.terminated) {
308         atf_tc_fail("incorrect terminated");
309     }
310     if (a.buffer != NULL) {
311         atf_tc_fail("incorrect buffer");
312     }
313 }
314 
315 ATF_TC(data_string_copy);
316 
317 ATF_TC_HEAD(data_string_copy, tc) {
318     atf_tc_set_md_var(tc, "descr", "data_string_copy basic test");
319 }
320 
321 ATF_TC_BODY(data_string_copy, tc) {
322     struct data_string a, b;
323     const char *str = "Lorem ipsum dolor sit amet orci aliquam.";
324 
325     /*
326      * Create the string we want to copy.
327          */
328     memset(&a, 0, sizeof(a));
329     a.len = strlen(str);
330     if (!buffer_allocate(&a.buffer, a.len, MDL)) {
331         atf_tc_fail("out of memory");
332     }
333     a.data = a.buffer->data;
334     memcpy(a.buffer->data, str, a.len);
335 
336     /*
337      * Copy the string, and confirm it works.
338      */
339     memset(&b, 0, sizeof(b));
340     data_string_copy(&b, &a, MDL);
341 
342     if (b.len != a.len) {
343         atf_tc_fail("incorrect length");
344     }
345     if (b.data != a.data) {
346         atf_tc_fail("incorrect data");
347     }
348     if (b.terminated != a.terminated) {
349         atf_tc_fail("incorrect terminated");
350     }
351     if (b.buffer != a.buffer) {
352         atf_tc_fail("incorrect buffer");
353     }
354 
355     /*
356      * Clean up.
357      */
358     data_string_forget(&b, MDL);
359     data_string_forget(&a, MDL);
360 }
361 
362 ATF_TC(data_string_copy_nobuf);
363 
364 ATF_TC_HEAD(data_string_copy_nobuf, tc) {
365     atf_tc_set_md_var(tc, "descr", "data_string_copy test, "
366                       "data_string without buffer");
367 }
368 
369 ATF_TC_BODY(data_string_copy_nobuf, tc) {
370     struct data_string a, b;
371     const char *str = "Lorem ipsum dolor sit amet cras amet.";
372 
373     /*
374      * Create the string we want to copy.
375      */
376     memset(&a, 0, sizeof(a));
377     a.len = strlen(str);
378     a.data = (const unsigned char *)str;
379     a.terminated = 1;
380 
381     /*
382      * Copy the string, and confirm it works.
383      */
384     memset(&b, 0, sizeof(b));
385     data_string_copy(&b, &a, MDL);
386 
387     if (b.len != a.len) {
388         atf_tc_fail("incorrect length");
389     }
390     if (b.data != a.data) {
391         atf_tc_fail("incorrect data");
392     }
393     if (b.terminated != a.terminated) {
394         atf_tc_fail("incorrect terminated");
395     }
396     if (b.buffer != a.buffer) {
397         atf_tc_fail("incorrect buffer");
398     }
399 
400     /*
401      * Clean up.
402      */
403     data_string_forget(&b, MDL);
404     data_string_forget(&a, MDL);
405 
406 }
407 
408 
409 ATF_TC(data_string_new);
410 
411 ATF_TC_HEAD(data_string_new, tc) {
412     atf_tc_set_md_var(tc, "descr", "data_string_new test, "
413                       "exercises data_string_new function");
414 }
415 
416 ATF_TC_BODY(data_string_new, tc) {
417     struct data_string new_string;
418     const char *src = "Really? Latin? ... geeks";
419     int len_arg = 0;
420     const char *error;
421 
422     /* Case 1: Call with an invalid data_string pointer, should fail */
423     if (data_string_new(NULL, src, len_arg, MDL)) {
424         atf_tc_fail("case 1: call should have failed");
425     }
426 
427     /* Case 2: Passing in NULL src should fail */
428     if (data_string_new(&new_string, NULL, 10, MDL)) {
429         atf_tc_fail("case 2: did not return success");
430     }
431 
432     /* Case 3: Call with valid params, length includes NULL */
433     len_arg = strlen(src) + 1;
434     if (data_string_new(&new_string, src, len_arg, MDL) == 0) {
435         atf_tc_fail("case 3: did not return success");
436     }
437 
438     error = checkString(&new_string, src);
439     ATF_REQUIRE_MSG((error == NULL), "case 3: %s", error);
440     data_string_forget(&new_string, MDL);
441 
442 
443     /* Case 4: Call with valid params, length does not include NULL */
444     len_arg = 7;
445     if (data_string_new(&new_string, src, len_arg, MDL) == 0) {
446         atf_tc_fail("case 4: did not return success");
447     }
448 
449     error = checkString(&new_string, "Really?");
450     ATF_REQUIRE_MSG((error == NULL), "case 4: %s", error);
451     data_string_forget(&new_string, MDL);
452 
453 
454     /* Case 5: Call with valid params, source string is "" */
455     len_arg = 0;
456     if (data_string_new(&new_string, "", len_arg, MDL) == 0) {
457         atf_tc_fail("case 5: did not return success");
458     }
459 
460     error = checkString(&new_string, "");
461     ATF_REQUIRE_MSG((error == NULL), "case 4: %s", error);
462     data_string_forget(&new_string, MDL);
463 
464 
465 }
466 
467 /* Helper function which tests validity of a data_string
468 *
469 * Verifies that the given data_string contains a null-terminated string
470 * equal to a given string.
471 *
472 * \param string data_string to test
473 * \param src text content string should contain
474 * \return returns NULL if data_string is validate or an error message
475 * describing why it is invalid
476 */
477 const char* checkString (struct data_string* string,
478     const char* src) {
479     int src_len = strlen(src);
480 
481     if (string->buffer == NULL) {
482         return ("buffer is NULL");
483     }
484 
485     if (string->data != string->buffer->data) {
486         return ("data not set to buffer->data");
487     }
488 
489     if (string->len != src_len) {
490         return ("len is wrong ");
491     }
492 
493     if (string->terminated != 1)  {
494         return ("terminated flag not set");
495     }
496 
497     if (memcmp(string->data, src, src_len + 1)) {
498         return ("data content wrong");
499     }
500 
501     return (NULL);
502 }
503 
504 ATF_TC(data_string_terminate);
505 
506 ATF_TC_HEAD(data_string_terminate, tc) {
507     atf_tc_set_md_var(tc, "descr", "data_string_terminate test, "
508                       "exercises data_string_terminate function");
509 }
510 
511 ATF_TC_BODY(data_string_terminate, tc) {
512     struct data_string new_string, copy_string;
513     const char *src = "Boring test string";
514 
515     /* Case 1: Call with an already terminated string.  The
516      * original structure shouldn't be touched.
517      */
518     memset(&new_string, 0, sizeof(new_string));
519     memset(&copy_string, 0, sizeof(copy_string));
520     if (data_string_new(&new_string, src, strlen(src), MDL) == 0) {
521 	atf_tc_fail("Case 1: unable to create new string");
522     }
523     memcpy(&copy_string, &new_string, sizeof(new_string));
524     if (data_string_terminate(&new_string, MDL) == 0) {
525 	atf_tc_fail("Case 1: unable to terminate string");
526     }
527     if (memcmp(&copy_string, &new_string, sizeof(new_string)) != 0) {
528 	atf_tc_fail("Case 1: structure modified");
529     }
530 
531     /* Case 2: Call with an unterminated string.  The
532      * original structure should be modified with a pointer
533      * to new memory for the string.
534      */
535     /* clear the termination flag, and shrink the string */
536     new_string.terminated = 0;
537     new_string.len -= 2;
538     memcpy(&copy_string, &new_string, sizeof(new_string));
539 
540     if (data_string_terminate(&new_string, MDL) == 0) {
541 	atf_tc_fail("Case 2: unable to terminate string");
542     }
543 
544     /* We expect the same string but in a differnet block of memory */
545     if ((new_string.terminated == 0) ||
546 	(&new_string.buffer == &copy_string.buffer) ||
547 	(new_string.len != copy_string.len) ||
548 	memcmp(new_string.data, src, new_string.len) ||
549 	new_string.data[new_string.len] != 0) {
550 	atf_tc_fail("Case 2: structure not modified correctly");
551     }
552 
553     /* get rid of the string, no need to get rid of copy as the
554      * string memory was freed during the terminate call */
555     data_string_forget(&new_string, MDL);
556 }
557 
558 void checkBuffer(size_t test_size, const char *file, int line) {
559     char *buf;
560     size_t max_size;
561     /* Determine the maximum size we may have
562      * Depending on configuration options we may be adding some
563      * space to the allocated buffer for debugging purposes
564      * so remove that as well.
565      */
566     max_size = ((size_t)-1) - DMDSIZE;
567 
568     if (test_size > max_size) {
569 	atf_tc_skip("Test size greater than max size, %zu", test_size);
570 	return;
571     }
572 
573     /* We allocate the buffer and then try to set the last character
574      * to a known value.
575      */
576     buf = dmalloc(test_size, file, line);
577     if (buf != NULL) {
578 	buf[test_size - 1] = 1;
579 	if (buf[test_size - 1] != 1)
580 	    atf_tc_fail("Value mismatch for index %zu", test_size);
581 	dfree(buf, file, line);
582     } else {
583 	atf_tc_skip("Unable to allocate memory %zu", test_size);
584     }
585 }
586 
587 #if 0
588 /* The max test presents some issues for some systems,
589  * leave it out for now
590  */
591 ATF_TC(dmalloc_max32);
592 
593 ATF_TC_HEAD(dmalloc_max32, tc) {
594     atf_tc_set_md_var(tc, "descr", "dmalloc_max32 test, "
595 		      "dmalloc 0xFFFFFFFF");
596 }
597 ATF_TC_BODY(dmalloc_max32, tc) {
598     checkBuffer(0XFFFFFFFF, MDL);
599 }
600 #endif
601 
602 ATF_TC(dmalloc_med1);
603 
604 ATF_TC_HEAD(dmalloc_med1, tc) {
605     atf_tc_set_md_var(tc, "descr", "dmalloc_med1 test, "
606 		      "dmalloc 0x80000000,");
607 }
608 ATF_TC_BODY(dmalloc_med1, tc) {
609     checkBuffer(0x80000000, MDL);
610 }
611 
612 ATF_TC(dmalloc_med2);
613 
614 ATF_TC_HEAD(dmalloc_med2, tc) {
615     atf_tc_set_md_var(tc, "descr", "dmalloc_med2 test, "
616 		      "dmalloc 0x7FFFFFFF, ");
617 }
618 ATF_TC_BODY(dmalloc_med2, tc) {
619     checkBuffer(0x7FFFFFFF,  MDL);
620 }
621 
622 ATF_TC(dmalloc_med3);
623 
624 ATF_TC_HEAD(dmalloc_med3, tc) {
625     atf_tc_set_md_var(tc, "descr", "dmalloc_med3 test, "
626 		      "dmalloc 0x10000000,");
627 }
628 ATF_TC_BODY(dmalloc_med3, tc) {
629     checkBuffer(0x10000000, MDL);
630 }
631 
632 ATF_TC(dmalloc_small);
633 
634 ATF_TC_HEAD(dmalloc_small, tc) {
635     atf_tc_set_md_var(tc, "descr", "dmalloc_small test, "
636 		      "dmalloc 0x0FFFFFFF");
637 }
638 ATF_TC_BODY(dmalloc_small, tc) {
639     checkBuffer(0X0FFFFFFF, MDL);
640 }
641 
642 ATF_TP_ADD_TCS(tp)
643 {
644     ATF_TP_ADD_TC(tp, buffer_allocate);
645     ATF_TP_ADD_TC(tp, buffer_reference);
646     ATF_TP_ADD_TC(tp, buffer_dereference);
647     ATF_TP_ADD_TC(tp, data_string_forget);
648     ATF_TP_ADD_TC(tp, data_string_forget_nobuf);
649     ATF_TP_ADD_TC(tp, data_string_copy);
650     ATF_TP_ADD_TC(tp, data_string_copy_nobuf);
651     ATF_TP_ADD_TC(tp, data_string_new);
652     ATF_TP_ADD_TC(tp, data_string_terminate);
653 #if 0
654     ATF_TP_ADD_TC(tp, dmalloc_max32);
655 #endif
656     ATF_TP_ADD_TC(tp, dmalloc_med1);
657     ATF_TP_ADD_TC(tp, dmalloc_med2);
658     ATF_TP_ADD_TC(tp, dmalloc_med3);
659     ATF_TP_ADD_TC(tp, dmalloc_small);
660 
661     return (atf_no_error());
662 }
663