Home | History | Annotate | Line # | Download | only in tests
      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