1 /* $NetBSD: dynstr_test.c,v 1.3 2014/12/10 04:38:03 christos Exp $ */ 2 3 /* 4 * Automated Testing Framework (atf) 5 * 6 * Copyright (c) 2008 The NetBSD Foundation, Inc. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 19 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 25 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 27 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 29 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <stdarg.h> 33 #include <stdint.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 38 #include <atf-c.h> 39 40 #include "dynstr.h" 41 #include "test_helpers.h" 42 43 /* --------------------------------------------------------------------- 44 * Tests for the "atf_dynstr" type. 45 * --------------------------------------------------------------------- */ 46 47 /* 48 * Constructors and destructors. 49 */ 50 51 ATF_TC(init); 52 ATF_TC_HEAD(init, tc) 53 { 54 atf_tc_set_md_var(tc, "descr", "Checks the empty constructor"); 55 } 56 ATF_TC_BODY(init, tc) 57 { 58 atf_dynstr_t str; 59 60 RE(atf_dynstr_init(&str)); 61 ATF_REQUIRE_EQ(atf_dynstr_length(&str), 0); 62 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0); 63 atf_dynstr_fini(&str); 64 } 65 66 static 67 void 68 init_fmt(atf_dynstr_t *str, const char *fmt, ...) 69 { 70 va_list ap; 71 72 va_start(ap, fmt); 73 RE(atf_dynstr_init_ap(str, fmt, ap)); 74 va_end(ap); 75 } 76 77 ATF_TC(init_ap); 78 ATF_TC_HEAD(init_ap, tc) 79 { 80 atf_tc_set_md_var(tc, "descr", "Checks the formatted constructor using " 81 "a va_list argument"); 82 } 83 ATF_TC_BODY(init_ap, tc) 84 { 85 atf_dynstr_t str; 86 87 init_fmt(&str, "String 1"); 88 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 1") == 0); 89 atf_dynstr_fini(&str); 90 91 init_fmt(&str, "String %d", 2); 92 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 2") == 0); 93 atf_dynstr_fini(&str); 94 95 init_fmt(&str, "%s %d", "String", 3); 96 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 3") == 0); 97 atf_dynstr_fini(&str); 98 99 init_fmt(&str, "%s%s%s%s%s%s%s", "This ", "should ", "be ", "a ", 100 "large ", "string ", "aaaabbbbccccdddd"); 101 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), 102 "This should be a large string " 103 "aaaabbbbccccdddd") == 0); 104 atf_dynstr_fini(&str); 105 } 106 107 ATF_TC(init_fmt); 108 ATF_TC_HEAD(init_fmt, tc) 109 { 110 atf_tc_set_md_var(tc, "descr", "Checks the formatted constructor using " 111 "a variable list of parameters"); 112 } 113 ATF_TC_BODY(init_fmt, tc) 114 { 115 atf_dynstr_t str; 116 117 RE(atf_dynstr_init_fmt(&str, "String 1")); 118 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 1") == 0); 119 atf_dynstr_fini(&str); 120 121 RE(atf_dynstr_init_fmt(&str, "String %d", 2)); 122 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 2") == 0); 123 atf_dynstr_fini(&str); 124 125 RE(atf_dynstr_init_fmt(&str, "%s %d", "String", 3)); 126 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 3") == 0); 127 atf_dynstr_fini(&str); 128 129 RE(atf_dynstr_init_fmt(&str, "%s%s%s%s%s%s%s", "This ", "should ", 130 "be ", "a ", "large ", "string ", 131 "aaaabbbbccccdddd")); 132 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), 133 "This should be a large string " 134 "aaaabbbbccccdddd") == 0); 135 atf_dynstr_fini(&str); 136 } 137 138 ATF_TC(init_raw); 139 ATF_TC_HEAD(init_raw, tc) 140 { 141 atf_tc_set_md_var(tc, "descr", "Checks the construction of a string " 142 "using a raw memory pointer"); 143 } 144 ATF_TC_BODY(init_raw, tc) 145 { 146 const char *src = "String 1, String 2"; 147 atf_dynstr_t str; 148 149 RE(atf_dynstr_init_raw(&str, src, 0)); 150 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0); 151 atf_dynstr_fini(&str); 152 153 RE(atf_dynstr_init_raw(&str, src, 8)); 154 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 1") == 0); 155 atf_dynstr_fini(&str); 156 157 RE(atf_dynstr_init_raw(&str, src + 10, 8)); 158 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 2") == 0); 159 atf_dynstr_fini(&str); 160 161 RE(atf_dynstr_init_raw(&str, "String\0Lost", 11)); 162 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String") == 0); 163 atf_dynstr_fini(&str); 164 165 { 166 atf_error_t err = atf_dynstr_init_raw(&str, "NULL", SIZE_MAX - 1); 167 ATF_REQUIRE(atf_is_error(err)); 168 ATF_REQUIRE(atf_error_is(err, "no_memory")); 169 atf_error_free(err); 170 } 171 } 172 173 ATF_TC(init_rep); 174 ATF_TC_HEAD(init_rep, tc) 175 { 176 atf_tc_set_md_var(tc, "descr", "Checks the construction of a string by " 177 "repeating characters"); 178 } 179 ATF_TC_BODY(init_rep, tc) 180 { 181 const size_t maxlen = 8192; 182 char buf[maxlen + 1]; 183 size_t i; 184 185 buf[0] = '\0'; 186 187 for (i = 0; i < maxlen; i++) { 188 atf_dynstr_t str; 189 190 RE(atf_dynstr_init_rep(&str, i, 'a')); 191 192 if (strcmp(atf_dynstr_cstring(&str), buf) != 0) { 193 fprintf(stderr, "Failed at iteration %zd\n", i); 194 atf_tc_fail("Failed to construct dynstr by repeating %zd " 195 "times the '%c' character", i, 'a'); 196 } 197 198 atf_dynstr_fini(&str); 199 200 strcat(buf, "a"); 201 } 202 203 { 204 atf_dynstr_t str; 205 atf_error_t err; 206 207 err = atf_dynstr_init_rep(&str, SIZE_MAX, 'a'); 208 ATF_REQUIRE(atf_is_error(err)); 209 ATF_REQUIRE(atf_error_is(err, "no_memory")); 210 atf_error_free(err); 211 212 err = atf_dynstr_init_rep(&str, SIZE_MAX - 1, 'a'); 213 ATF_REQUIRE(atf_is_error(err)); 214 ATF_REQUIRE(atf_error_is(err, "no_memory")); 215 atf_error_free(err); 216 } 217 } 218 219 ATF_TC(init_substr); 220 ATF_TC_HEAD(init_substr, tc) 221 { 222 atf_tc_set_md_var(tc, "descr", "Checks the construction of a string " 223 "using a substring of another one"); 224 } 225 ATF_TC_BODY(init_substr, tc) 226 { 227 atf_dynstr_t src; 228 atf_dynstr_t str; 229 230 RE(atf_dynstr_init_fmt(&src, "Str 1, Str 2")); 231 232 RE(atf_dynstr_init_substr(&str, &src, 0, 0)); 233 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0); 234 atf_dynstr_fini(&str); 235 236 RE(atf_dynstr_init_substr(&str, &src, 0, atf_dynstr_npos)); 237 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "Str 1, Str 2") == 0); 238 atf_dynstr_fini(&str); 239 240 RE(atf_dynstr_init_substr(&str, &src, 0, 100)); 241 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "Str 1, Str 2") == 0); 242 atf_dynstr_fini(&str); 243 244 RE(atf_dynstr_init_substr(&str, &src, 0, 5)); 245 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "Str 1") == 0); 246 atf_dynstr_fini(&str); 247 248 RE(atf_dynstr_init_substr(&str, &src, 100, atf_dynstr_npos)); 249 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0); 250 atf_dynstr_fini(&str); 251 252 RE(atf_dynstr_init_substr(&str, &src, 7, atf_dynstr_npos)); 253 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "Str 2") == 0); 254 atf_dynstr_fini(&str); 255 256 atf_dynstr_fini(&src); 257 } 258 259 ATF_TC(copy); 260 ATF_TC_HEAD(copy, tc) 261 { 262 atf_tc_set_md_var(tc, "descr", "Checks the atf_dynstr_copy constructor"); 263 } 264 ATF_TC_BODY(copy, tc) 265 { 266 atf_dynstr_t str, str2; 267 268 RE(atf_dynstr_init_fmt(&str, "Test string")); 269 RE(atf_dynstr_copy(&str2, &str)); 270 271 ATF_REQUIRE(atf_equal_dynstr_dynstr(&str, &str2)); 272 273 RE(atf_dynstr_append_fmt(&str2, " non-shared text")); 274 275 ATF_REQUIRE(!atf_equal_dynstr_dynstr(&str, &str2)); 276 277 atf_dynstr_fini(&str2); 278 atf_dynstr_fini(&str); 279 } 280 281 ATF_TC(fini_disown); 282 ATF_TC_HEAD(fini_disown, tc) 283 { 284 atf_tc_set_md_var(tc, "descr", "Checks grabbing ownership of the " 285 "internal plain C string"); 286 } 287 ATF_TC_BODY(fini_disown, tc) 288 { 289 const char *cstr; 290 char *cstr2; 291 atf_dynstr_t str; 292 293 RE(atf_dynstr_init_fmt(&str, "Test string 1")); 294 cstr = atf_dynstr_cstring(&str); 295 cstr2 = atf_dynstr_fini_disown(&str); 296 297 ATF_REQUIRE_EQ(cstr, cstr2); 298 free(cstr2); 299 } 300 301 /* 302 * Getters. 303 */ 304 305 ATF_TC(cstring); 306 ATF_TC_HEAD(cstring, tc) 307 { 308 atf_tc_set_md_var(tc, "descr", "Checks the method to obtain a plain C " 309 "string"); 310 } 311 ATF_TC_BODY(cstring, tc) 312 { 313 const char *cstr; 314 atf_dynstr_t str; 315 316 RE(atf_dynstr_init_fmt(&str, "Test string 1")); 317 cstr = atf_dynstr_cstring(&str); 318 ATF_REQUIRE(cstr != NULL); 319 ATF_REQUIRE(strcmp(cstr, "Test string 1") == 0); 320 atf_dynstr_fini(&str); 321 322 RE(atf_dynstr_init_fmt(&str, "Test string 2")); 323 cstr = atf_dynstr_cstring(&str); 324 ATF_REQUIRE(cstr != NULL); 325 ATF_REQUIRE(strcmp(cstr, "Test string 2") == 0); 326 atf_dynstr_fini(&str); 327 } 328 329 ATF_TC(length); 330 ATF_TC_HEAD(length, tc) 331 { 332 atf_tc_set_md_var(tc, "descr", "Checks the method to obtain the length"); 333 } 334 ATF_TC_BODY(length, tc) 335 { 336 size_t i; 337 338 for (i = 0; i < 8192; i++) { 339 atf_dynstr_t str; 340 RE(atf_dynstr_init_rep(&str, i, 'a')); 341 ATF_REQUIRE_EQ(atf_dynstr_length(&str), i); 342 atf_dynstr_fini(&str); 343 } 344 } 345 346 ATF_TC(rfind_ch); 347 ATF_TC_HEAD(rfind_ch, tc) 348 { 349 atf_tc_set_md_var(tc, "descr", "Checks the method to locate the first " 350 "occurrence of a character starting from the end"); 351 } 352 ATF_TC_BODY(rfind_ch, tc) 353 { 354 atf_dynstr_t str; 355 356 RE(atf_dynstr_init_fmt(&str, "Foo1/Bar2/,.Baz")); 357 358 ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, '\0'), atf_dynstr_npos); 359 360 ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, '0'), atf_dynstr_npos); 361 ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, 'b'), atf_dynstr_npos); 362 363 ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, 'F'), 0); 364 ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, '/'), 9); 365 ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, 'a'), 13); 366 ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, 'z'), 14); 367 368 atf_dynstr_fini(&str); 369 } 370 371 /* 372 * Modifiers. 373 */ 374 375 static 376 void 377 check_append(atf_error_t (*append)(atf_dynstr_t *, const char *, ...)) 378 { 379 const size_t maxlen = 8192; 380 char buf[maxlen + 1]; 381 size_t i; 382 atf_dynstr_t str; 383 384 printf("Appending with plain string\n"); 385 buf[0] = '\0'; 386 RE(atf_dynstr_init(&str)); 387 for (i = 0; i < maxlen; i++) { 388 if (strcmp(atf_dynstr_cstring(&str), buf) != 0) { 389 fprintf(stderr, "Failed at iteration %zd\n", i); 390 atf_tc_fail("Failed to append character at iteration %zd", i); 391 } 392 393 RE(append(&str, "a")); 394 strcat(buf, "a"); 395 } 396 atf_dynstr_fini(&str); 397 398 printf("Appending with formatted string\n"); 399 buf[0] = '\0'; 400 RE(atf_dynstr_init(&str)); 401 for (i = 0; i < maxlen; i++) { 402 if (strcmp(atf_dynstr_cstring(&str), buf) != 0) { 403 fprintf(stderr, "Failed at iteration %zd\n", i); 404 atf_tc_fail("Failed to append character at iteration %zd", i); 405 } 406 407 RE(append(&str, "%s", "a")); 408 strcat(buf, "a"); 409 } 410 atf_dynstr_fini(&str); 411 } 412 413 static 414 atf_error_t 415 append_ap_aux(atf_dynstr_t *str, const char *fmt, ...) 416 { 417 va_list ap; 418 atf_error_t err; 419 420 va_start(ap, fmt); 421 err = atf_dynstr_append_ap(str, fmt, ap); 422 va_end(ap); 423 424 return err; 425 } 426 427 ATF_TC(append_ap); 428 ATF_TC_HEAD(append_ap, tc) 429 { 430 atf_tc_set_md_var(tc, "descr", "Checks that appending a string to " 431 "another one works"); 432 } 433 ATF_TC_BODY(append_ap, tc) 434 { 435 check_append(append_ap_aux); 436 } 437 438 ATF_TC(append_fmt); 439 ATF_TC_HEAD(append_fmt, tc) 440 { 441 atf_tc_set_md_var(tc, "descr", "Checks that appending a string to " 442 "another one works"); 443 } 444 ATF_TC_BODY(append_fmt, tc) 445 { 446 check_append(atf_dynstr_append_fmt); 447 } 448 449 ATF_TC(clear); 450 ATF_TC_HEAD(clear, tc) 451 { 452 atf_tc_set_md_var(tc, "descr", "Checks clearing a string"); 453 } 454 ATF_TC_BODY(clear, tc) 455 { 456 atf_dynstr_t str; 457 458 printf("Clear an empty string\n"); 459 RE(atf_dynstr_init(&str)); 460 atf_dynstr_clear(&str); 461 ATF_REQUIRE_EQ(atf_dynstr_length(&str), 0); 462 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0); 463 atf_dynstr_fini(&str); 464 465 printf("Clear a non-empty string\n"); 466 RE(atf_dynstr_init_fmt(&str, "Not empty")); 467 ATF_REQUIRE_EQ(atf_dynstr_length(&str), strlen("Not empty")); 468 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "Not empty") == 0); 469 atf_dynstr_clear(&str); 470 ATF_REQUIRE_EQ(atf_dynstr_length(&str), 0); 471 ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0); 472 atf_dynstr_fini(&str); 473 } 474 475 static 476 void 477 check_prepend(atf_error_t (*prepend)(atf_dynstr_t *, const char *, ...)) 478 { 479 const size_t maxlen = 8192; 480 char buf[maxlen + 1]; 481 size_t i; 482 atf_dynstr_t str; 483 484 printf("Prepending with plain string\n"); 485 buf[0] = '\0'; 486 RE(atf_dynstr_init(&str)); 487 for (i = 0; i < maxlen; i++) { 488 if (strcmp(atf_dynstr_cstring(&str), buf) != 0) { 489 fprintf(stderr, "Failed at iteration %zd\n", i); 490 atf_tc_fail("Failed to prepend character at iteration %zd", i); 491 } 492 493 memmove(buf + 1, buf, i + 1); 494 if (i % 2 == 0) { 495 RE(prepend(&str, "%s", "a")); 496 buf[0] = 'a'; 497 } else { 498 RE(prepend(&str, "%s", "b")); 499 buf[0] = 'b'; 500 } 501 } 502 atf_dynstr_fini(&str); 503 504 printf("Prepending with formatted string\n"); 505 buf[0] = '\0'; 506 RE(atf_dynstr_init(&str)); 507 for (i = 0; i < maxlen; i++) { 508 if (strcmp(atf_dynstr_cstring(&str), buf) != 0) { 509 fprintf(stderr, "Failed at iteration %zd\n", i); 510 atf_tc_fail("Failed to prepend character at iteration %zd", i); 511 } 512 513 memmove(buf + 1, buf, i + 1); 514 if (i % 2 == 0) { 515 RE(prepend(&str, "%s", "a")); 516 buf[0] = 'a'; 517 } else { 518 RE(prepend(&str, "%s", "b")); 519 buf[0] = 'b'; 520 } 521 } 522 atf_dynstr_fini(&str); 523 } 524 525 static 526 atf_error_t 527 prepend_ap_aux(atf_dynstr_t *str, const char *fmt, ...) 528 { 529 va_list ap; 530 atf_error_t err; 531 532 va_start(ap, fmt); 533 err = atf_dynstr_prepend_ap(str, fmt, ap); 534 va_end(ap); 535 536 return err; 537 } 538 539 ATF_TC(prepend_ap); 540 ATF_TC_HEAD(prepend_ap, tc) 541 { 542 atf_tc_set_md_var(tc, "descr", "Checks that prepending a string to " 543 "another one works"); 544 } 545 ATF_TC_BODY(prepend_ap, tc) 546 { 547 check_prepend(prepend_ap_aux); 548 } 549 550 ATF_TC(prepend_fmt); 551 ATF_TC_HEAD(prepend_fmt, tc) 552 { 553 atf_tc_set_md_var(tc, "descr", "Checks that prepending a string to " 554 "another one works"); 555 } 556 ATF_TC_BODY(prepend_fmt, tc) 557 { 558 check_prepend(atf_dynstr_prepend_fmt); 559 } 560 561 /* 562 * Operators. 563 */ 564 565 ATF_TC(equal_cstring); 566 ATF_TC_HEAD(equal_cstring, tc) 567 { 568 atf_tc_set_md_var(tc, "descr", "Checks the atf_equal_dynstr_cstring " 569 "function"); 570 } 571 ATF_TC_BODY(equal_cstring, tc) 572 { 573 atf_dynstr_t str; 574 575 RE(atf_dynstr_init(&str)); 576 ATF_REQUIRE( atf_equal_dynstr_cstring(&str, "")); 577 ATF_REQUIRE(!atf_equal_dynstr_cstring(&str, "Test")); 578 atf_dynstr_fini(&str); 579 580 RE(atf_dynstr_init_fmt(&str, "Test")); 581 ATF_REQUIRE( atf_equal_dynstr_cstring(&str, "Test")); 582 ATF_REQUIRE(!atf_equal_dynstr_cstring(&str, "")); 583 ATF_REQUIRE(!atf_equal_dynstr_cstring(&str, "Tes")); 584 ATF_REQUIRE(!atf_equal_dynstr_cstring(&str, "Test ")); 585 atf_dynstr_fini(&str); 586 } 587 588 ATF_TC(equal_dynstr); 589 ATF_TC_HEAD(equal_dynstr, tc) 590 { 591 atf_tc_set_md_var(tc, "descr", "Checks the atf_equal_dynstr_dynstr " 592 "function"); 593 } 594 ATF_TC_BODY(equal_dynstr, tc) 595 { 596 atf_dynstr_t str, str2; 597 598 RE(atf_dynstr_init(&str)); 599 RE(atf_dynstr_init_fmt(&str2, "Test")); 600 ATF_REQUIRE( atf_equal_dynstr_dynstr(&str, &str)); 601 ATF_REQUIRE(!atf_equal_dynstr_dynstr(&str, &str2)); 602 atf_dynstr_fini(&str2); 603 atf_dynstr_fini(&str); 604 } 605 606 /* --------------------------------------------------------------------- 607 * Main. 608 * --------------------------------------------------------------------- */ 609 610 ATF_TP_ADD_TCS(tp) 611 { 612 /* Constructors and destructors. */ 613 ATF_TP_ADD_TC(tp, init); 614 ATF_TP_ADD_TC(tp, init_ap); 615 ATF_TP_ADD_TC(tp, init_fmt); 616 ATF_TP_ADD_TC(tp, init_raw); 617 ATF_TP_ADD_TC(tp, init_rep); 618 ATF_TP_ADD_TC(tp, init_substr); 619 ATF_TP_ADD_TC(tp, copy); 620 ATF_TP_ADD_TC(tp, fini_disown); 621 622 /* Getters. */ 623 ATF_TP_ADD_TC(tp, cstring); 624 ATF_TP_ADD_TC(tp, length); 625 ATF_TP_ADD_TC(tp, rfind_ch); 626 627 /* Modifiers. */ 628 ATF_TP_ADD_TC(tp, append_ap); 629 ATF_TP_ADD_TC(tp, append_fmt); 630 ATF_TP_ADD_TC(tp, clear); 631 ATF_TP_ADD_TC(tp, prepend_ap); 632 ATF_TP_ADD_TC(tp, prepend_fmt); 633 634 /* Operators. */ 635 ATF_TP_ADD_TC(tp, equal_cstring); 636 ATF_TP_ADD_TC(tp, equal_dynstr); 637 638 return atf_no_error(); 639 } 640