test_alloc.c revision 1.1
1/* $NetBSD: test_alloc.c,v 1.1 2018/04/07 22:34:26 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 46static const char* checkString (struct data_string* ds, const char *src); 47 48ATF_TC(buffer_allocate); 49 50ATF_TC_HEAD(buffer_allocate, tc) { 51 atf_tc_set_md_var(tc, "descr", "buffer_allocate basic test"); 52} 53 54ATF_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 91ATF_TC(buffer_reference); 92 93ATF_TC_HEAD(buffer_reference, tc) { 94 atf_tc_set_md_var(tc, "descr", "buffer_reference basic test"); 95} 96 97ATF_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 152ATF_TC(buffer_dereference); 153 154ATF_TC_HEAD(buffer_dereference, tc) { 155 atf_tc_set_md_var(tc, "descr", "buffer_dereference basic test"); 156} 157 158ATF_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 221ATF_TC(data_string_forget); 222 223ATF_TC_HEAD(data_string_forget, tc) { 224 atf_tc_set_md_var(tc, "descr", "data_string_forget basic test"); 225} 226 227ATF_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 277ATF_TC(data_string_forget_nobuf); 278 279ATF_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 284ATF_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 315ATF_TC(data_string_copy); 316 317ATF_TC_HEAD(data_string_copy, tc) { 318 atf_tc_set_md_var(tc, "descr", "data_string_copy basic test"); 319} 320 321ATF_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 362ATF_TC(data_string_copy_nobuf); 363 364ATF_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 369ATF_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 409ATF_TC(data_string_new); 410 411ATF_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 416ATF_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*/ 477const 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 504ATF_TC(data_string_terminate); 505 506ATF_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 511ATF_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 558void 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 */ 591ATF_TC(dmalloc_max32); 592 593ATF_TC_HEAD(dmalloc_max32, tc) { 594 atf_tc_set_md_var(tc, "descr", "dmalloc_max32 test, " 595 "dmalloc 0xFFFFFFFF"); 596} 597ATF_TC_BODY(dmalloc_max32, tc) { 598 checkBuffer(0XFFFFFFFF, MDL); 599} 600#endif 601 602ATF_TC(dmalloc_med1); 603 604ATF_TC_HEAD(dmalloc_med1, tc) { 605 atf_tc_set_md_var(tc, "descr", "dmalloc_med1 test, " 606 "dmalloc 0x80000000,"); 607} 608ATF_TC_BODY(dmalloc_med1, tc) { 609 checkBuffer(0x80000000, MDL); 610} 611 612ATF_TC(dmalloc_med2); 613 614ATF_TC_HEAD(dmalloc_med2, tc) { 615 atf_tc_set_md_var(tc, "descr", "dmalloc_med2 test, " 616 "dmalloc 0x7FFFFFFF, "); 617} 618ATF_TC_BODY(dmalloc_med2, tc) { 619 checkBuffer(0x7FFFFFFF, MDL); 620} 621 622ATF_TC(dmalloc_med3); 623 624ATF_TC_HEAD(dmalloc_med3, tc) { 625 atf_tc_set_md_var(tc, "descr", "dmalloc_med3 test, " 626 "dmalloc 0x10000000,"); 627} 628ATF_TC_BODY(dmalloc_med3, tc) { 629 checkBuffer(0x10000000, MDL); 630} 631 632ATF_TC(dmalloc_small); 633 634ATF_TC_HEAD(dmalloc_small, tc) { 635 atf_tc_set_md_var(tc, "descr", "dmalloc_small test, " 636 "dmalloc 0x0FFFFFFF"); 637} 638ATF_TC_BODY(dmalloc_small, tc) { 639 checkBuffer(0X0FFFFFFF, MDL); 640} 641 642ATF_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