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
ATF_TC_HEAD(buffer_allocate,tc)50 ATF_TC_HEAD(buffer_allocate, tc) {
51 atf_tc_set_md_var(tc, "descr", "buffer_allocate basic test");
52 }
53
ATF_TC_BODY(buffer_allocate,tc)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
ATF_TC_HEAD(buffer_reference,tc)93 ATF_TC_HEAD(buffer_reference, tc) {
94 atf_tc_set_md_var(tc, "descr", "buffer_reference basic test");
95 }
96
ATF_TC_BODY(buffer_reference,tc)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
ATF_TC_HEAD(buffer_dereference,tc)154 ATF_TC_HEAD(buffer_dereference, tc) {
155 atf_tc_set_md_var(tc, "descr", "buffer_dereference basic test");
156 }
157
ATF_TC_BODY(buffer_dereference,tc)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
ATF_TC_HEAD(data_string_forget,tc)223 ATF_TC_HEAD(data_string_forget, tc) {
224 atf_tc_set_md_var(tc, "descr", "data_string_forget basic test");
225 }
226
ATF_TC_BODY(data_string_forget,tc)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
ATF_TC_HEAD(data_string_forget_nobuf,tc)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
ATF_TC_BODY(data_string_forget_nobuf,tc)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
ATF_TC_HEAD(data_string_copy,tc)317 ATF_TC_HEAD(data_string_copy, tc) {
318 atf_tc_set_md_var(tc, "descr", "data_string_copy basic test");
319 }
320
ATF_TC_BODY(data_string_copy,tc)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
ATF_TC_HEAD(data_string_copy_nobuf,tc)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
ATF_TC_BODY(data_string_copy_nobuf,tc)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
ATF_TC_HEAD(data_string_new,tc)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
ATF_TC_BODY(data_string_new,tc)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 */
checkString(struct data_string * string,const char * src)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
ATF_TC_HEAD(data_string_terminate,tc)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
ATF_TC_BODY(data_string_terminate,tc)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(©_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(©_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(©_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(©_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 == ©_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
checkBuffer(size_t test_size,const char * file,int line)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
ATF_TC_HEAD(dmalloc_med1,tc)604 ATF_TC_HEAD(dmalloc_med1, tc) {
605 atf_tc_set_md_var(tc, "descr", "dmalloc_med1 test, "
606 "dmalloc 0x80000000,");
607 }
ATF_TC_BODY(dmalloc_med1,tc)608 ATF_TC_BODY(dmalloc_med1, tc) {
609 checkBuffer(0x80000000, MDL);
610 }
611
612 ATF_TC(dmalloc_med2);
613
ATF_TC_HEAD(dmalloc_med2,tc)614 ATF_TC_HEAD(dmalloc_med2, tc) {
615 atf_tc_set_md_var(tc, "descr", "dmalloc_med2 test, "
616 "dmalloc 0x7FFFFFFF, ");
617 }
ATF_TC_BODY(dmalloc_med2,tc)618 ATF_TC_BODY(dmalloc_med2, tc) {
619 checkBuffer(0x7FFFFFFF, MDL);
620 }
621
622 ATF_TC(dmalloc_med3);
623
ATF_TC_HEAD(dmalloc_med3,tc)624 ATF_TC_HEAD(dmalloc_med3, tc) {
625 atf_tc_set_md_var(tc, "descr", "dmalloc_med3 test, "
626 "dmalloc 0x10000000,");
627 }
ATF_TC_BODY(dmalloc_med3,tc)628 ATF_TC_BODY(dmalloc_med3, tc) {
629 checkBuffer(0x10000000, MDL);
630 }
631
632 ATF_TC(dmalloc_small);
633
ATF_TC_HEAD(dmalloc_small,tc)634 ATF_TC_HEAD(dmalloc_small, tc) {
635 atf_tc_set_md_var(tc, "descr", "dmalloc_small test, "
636 "dmalloc 0x0FFFFFFF");
637 }
ATF_TC_BODY(dmalloc_small,tc)638 ATF_TC_BODY(dmalloc_small, tc) {
639 checkBuffer(0X0FFFFFFF, MDL);
640 }
641
ATF_TP_ADD_TCS(tp)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