1b824378bSEnji Cooper /*- 2148a8da8SEnji Cooper * Copyright (c) 2017 Enji Cooper <ngie@freebsd.org> 3b824378bSEnji Cooper * 4b824378bSEnji Cooper * Redistribution and use in source and binary forms, with or without 5b824378bSEnji Cooper * modification, are permitted provided that the following conditions 6b824378bSEnji Cooper * are met: 7b824378bSEnji Cooper * 1. Redistributions of source code must retain the above copyright 8b824378bSEnji Cooper * notice, this list of conditions and the following disclaimer. 9b824378bSEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 10b824378bSEnji Cooper * notice, this list of conditions and the following disclaimer in the 11b824378bSEnji Cooper * documentation and/or other materials provided with the distribution. 12b824378bSEnji Cooper * 13b824378bSEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14b824378bSEnji Cooper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15b824378bSEnji Cooper * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16b824378bSEnji Cooper * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17b824378bSEnji Cooper * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18b824378bSEnji Cooper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19b824378bSEnji Cooper * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20b824378bSEnji Cooper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21b824378bSEnji Cooper * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22b824378bSEnji Cooper * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23b824378bSEnji Cooper * SUCH DAMAGE. 24b824378bSEnji Cooper */ 25b824378bSEnji Cooper 26b824378bSEnji Cooper #include <sys/param.h> 27b824378bSEnji Cooper #include <sys/sbuf.h> 28*991bd461SEnji Cooper 29*991bd461SEnji Cooper #include <atf-c.h> 30b824378bSEnji Cooper #include <errno.h> 31b824378bSEnji Cooper #include <stdarg.h> 32b824378bSEnji Cooper #include <stdio.h> 33b824378bSEnji Cooper #include <stdlib.h> 34b824378bSEnji Cooper #include <string.h> 35b824378bSEnji Cooper #include <unistd.h> 36b824378bSEnji Cooper 37b824378bSEnji Cooper #include "sbuf_test_common.h" 38b824378bSEnji Cooper 39b824378bSEnji Cooper static char test_string[] = "this is a test string"; 40b824378bSEnji Cooper #define TEST_STRING_CHOP_COUNT 5 41b824378bSEnji Cooper _Static_assert(nitems(test_string) > TEST_STRING_CHOP_COUNT, 42b824378bSEnji Cooper "test_string is too short"); 43b824378bSEnji Cooper 44b824378bSEnji Cooper ATF_TC_WITHOUT_HEAD(sbuf_clear_test); 45b824378bSEnji Cooper ATF_TC_BODY(sbuf_clear_test, tc) 46b824378bSEnji Cooper { 47b824378bSEnji Cooper struct sbuf *sb; 48b824378bSEnji Cooper ssize_t buf_len; 49b824378bSEnji Cooper pid_t child_proc; 50b824378bSEnji Cooper 51b824378bSEnji Cooper sb = sbuf_new_auto(); 52b824378bSEnji Cooper ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s", 53b824378bSEnji Cooper strerror(errno)); 54b824378bSEnji Cooper 55b824378bSEnji Cooper ATF_REQUIRE_MSG(sbuf_cat(sb, test_string) == 0, "sbuf_cat failed"); 56b824378bSEnji Cooper 57b824378bSEnji Cooper /* 58b824378bSEnji Cooper * Cheat so we can get the contents of the buffer before calling 59b824378bSEnji Cooper * sbuf_finish(3) below, making additional sbuf changes impossible. 60b824378bSEnji Cooper */ 61b824378bSEnji Cooper child_proc = atf_utils_fork(); 62b824378bSEnji Cooper if (child_proc == 0) { 637d7db529SConrad Meyer ATF_REQUIRE_EQ_MSG(0, sbuf_finish(sb), "sbuf_finish failed: %s", 647d7db529SConrad Meyer strerror(errno)); 657d7db529SConrad Meyer 66b824378bSEnji Cooper sbuf_putbuf(sb); 67b824378bSEnji Cooper exit(0); 68b824378bSEnji Cooper } 69b824378bSEnji Cooper atf_utils_wait(child_proc, 0, test_string, ""); 70b824378bSEnji Cooper 71b824378bSEnji Cooper sbuf_clear(sb); 72b824378bSEnji Cooper 73b824378bSEnji Cooper ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s", 74b824378bSEnji Cooper strerror(errno)); 75b824378bSEnji Cooper 76b824378bSEnji Cooper buf_len = sbuf_len(sb); 77b824378bSEnji Cooper ATF_REQUIRE_MSG(buf_len == 0, "sbuf_len (%zd) != 0", buf_len); 78*991bd461SEnji Cooper ATF_REQUIRE_STREQ_MSG(sbuf_data(sb), "", "sbuf (\"%s\") was not empty", 79*991bd461SEnji Cooper sbuf_data(sb)); 80b824378bSEnji Cooper 81b824378bSEnji Cooper sbuf_delete(sb); 82b824378bSEnji Cooper } 83b824378bSEnji Cooper 84b824378bSEnji Cooper ATF_TC_WITHOUT_HEAD(sbuf_done_and_sbuf_finish_test); 85b824378bSEnji Cooper ATF_TC_BODY(sbuf_done_and_sbuf_finish_test, tc) 86b824378bSEnji Cooper { 87b824378bSEnji Cooper struct sbuf *sb; 88b824378bSEnji Cooper 89b824378bSEnji Cooper sb = sbuf_new_auto(); 90b824378bSEnji Cooper ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s", 91b824378bSEnji Cooper strerror(errno)); 92b824378bSEnji Cooper 93b824378bSEnji Cooper ATF_CHECK(sbuf_done(sb) == 0); 94b824378bSEnji Cooper 95b824378bSEnji Cooper ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s", 96b824378bSEnji Cooper strerror(errno)); 97b824378bSEnji Cooper 98b824378bSEnji Cooper ATF_CHECK(sbuf_done(sb) != 0); 99b824378bSEnji Cooper 100b824378bSEnji Cooper sbuf_delete(sb); 101b824378bSEnji Cooper } 102b824378bSEnji Cooper 1037d7db529SConrad Meyer static int 1047d7db529SConrad Meyer drain_ret0(void *arg, const char *data, int len) 1057d7db529SConrad Meyer { 1067d7db529SConrad Meyer (void)arg; 1077d7db529SConrad Meyer (void)data; 1087d7db529SConrad Meyer (void)len; 1097d7db529SConrad Meyer 1107d7db529SConrad Meyer return (0); 1117d7db529SConrad Meyer } 1127d7db529SConrad Meyer 1137d7db529SConrad Meyer ATF_TC_WITHOUT_HEAD(sbuf_drain_ret0_test); 1147d7db529SConrad Meyer ATF_TC_BODY(sbuf_drain_ret0_test, tc) 1157d7db529SConrad Meyer { 1167d7db529SConrad Meyer struct sbuf *sb; 1177d7db529SConrad Meyer 1187d7db529SConrad Meyer sb = sbuf_new_auto(); 1197d7db529SConrad Meyer 1207d7db529SConrad Meyer sbuf_set_drain(sb, drain_ret0, NULL); 1217d7db529SConrad Meyer 1227d7db529SConrad Meyer sbuf_cat(sb, test_string); 1237d7db529SConrad Meyer 1247d7db529SConrad Meyer ATF_CHECK_EQ_MSG(-1, sbuf_finish(sb), 1257d7db529SConrad Meyer "required to return error when drain func returns 0"); 1267d7db529SConrad Meyer ATF_CHECK_EQ_MSG(EDEADLK, errno, 1277d7db529SConrad Meyer "errno required to be EDEADLK when drain func returns 0"); 1287d7db529SConrad Meyer } 1297d7db529SConrad Meyer 130b824378bSEnji Cooper ATF_TC_WITHOUT_HEAD(sbuf_len_test); 131b824378bSEnji Cooper ATF_TC_BODY(sbuf_len_test, tc) 132b824378bSEnji Cooper { 133b824378bSEnji Cooper struct sbuf *sb; 134b824378bSEnji Cooper ssize_t buf_len, test_string_len; 135b824378bSEnji Cooper int i; 136b824378bSEnji Cooper 137b824378bSEnji Cooper sb = sbuf_new_auto(); 138b824378bSEnji Cooper ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s", 139b824378bSEnji Cooper strerror(errno)); 140b824378bSEnji Cooper 141b824378bSEnji Cooper test_string_len = strlen(test_string); 142b824378bSEnji Cooper for (i = 0; i < 20; i++) { 143b824378bSEnji Cooper buf_len = sbuf_len(sb); 144b824378bSEnji Cooper ATF_REQUIRE_MSG(buf_len == (ssize_t)(i * test_string_len), 145b824378bSEnji Cooper "sbuf_len (%zd) != %zu", buf_len, i * test_string_len); 146*991bd461SEnji Cooper ATF_REQUIRE_MSG(sbuf_cat(sb, test_string) == 0, 147*991bd461SEnji Cooper "sbuf_cat failed"); 148b824378bSEnji Cooper } 149b824378bSEnji Cooper 150b824378bSEnji Cooper #ifdef HAVE_SBUF_SET_FLAGS 151b824378bSEnji Cooper sbuf_set_flags(sb, SBUF_INCLUDENUL); 152b824378bSEnji Cooper ATF_REQUIRE_MSG((ssize_t)(i * test_string_len + 1) == sbuf_len(sb), 153b824378bSEnji Cooper "sbuf_len(..) didn't report the NUL char"); 154b824378bSEnji Cooper #endif 155b824378bSEnji Cooper 156b824378bSEnji Cooper ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s", 157b824378bSEnji Cooper strerror(errno)); 158b824378bSEnji Cooper 159b824378bSEnji Cooper sbuf_delete(sb); 160b824378bSEnji Cooper } 161b824378bSEnji Cooper 1627d7db529SConrad Meyer ATF_TC_WITHOUT_HEAD(sbuf_new_fixedlen); 1637d7db529SConrad Meyer ATF_TC_BODY(sbuf_new_fixedlen, tc) 1647d7db529SConrad Meyer { 1657d7db529SConrad Meyer char buf[strlen(test_string) + 1]; 1667d7db529SConrad Meyer struct sbuf sb; 1677d7db529SConrad Meyer pid_t child_proc; 1687d7db529SConrad Meyer 1697d7db529SConrad Meyer sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN); 1707d7db529SConrad Meyer 1717d7db529SConrad Meyer sbuf_cat(&sb, test_string); 1727d7db529SConrad Meyer 1737d7db529SConrad Meyer child_proc = atf_utils_fork(); 1747d7db529SConrad Meyer if (child_proc == 0) { 175*991bd461SEnji Cooper ATF_REQUIRE_EQ_MSG(0, sbuf_finish(&sb), 176*991bd461SEnji Cooper "sbuf_finish failed: %s", strerror(errno)); 1777d7db529SConrad Meyer 1787d7db529SConrad Meyer sbuf_putbuf(&sb); 1797d7db529SConrad Meyer exit(0); 1807d7db529SConrad Meyer } 1817d7db529SConrad Meyer atf_utils_wait(child_proc, 0, test_string, ""); 1827d7db529SConrad Meyer 1837d7db529SConrad Meyer sbuf_putc(&sb, ' '); 1847d7db529SConrad Meyer 185*991bd461SEnji Cooper ATF_CHECK_EQ_MSG(-1, sbuf_finish(&sb), 186*991bd461SEnji Cooper "failed to return error on overflow"); 1877d7db529SConrad Meyer 1887d7db529SConrad Meyer sbuf_delete(&sb); 1897d7db529SConrad Meyer } 1907d7db529SConrad Meyer 191b824378bSEnji Cooper ATF_TC_WITHOUT_HEAD(sbuf_setpos_test); 192b824378bSEnji Cooper ATF_TC_BODY(sbuf_setpos_test, tc) 193b824378bSEnji Cooper { 194b824378bSEnji Cooper struct sbuf *sb; 195b824378bSEnji Cooper size_t test_string_chopped_len, test_string_len; 196b824378bSEnji Cooper ssize_t buf_len; 197b824378bSEnji Cooper 198b824378bSEnji Cooper sb = sbuf_new_auto(); 199b824378bSEnji Cooper ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s", 200b824378bSEnji Cooper strerror(errno)); 201b824378bSEnji Cooper 202b824378bSEnji Cooper /* 203b824378bSEnji Cooper * An obvious sanity check -- if sbuf_len(..) lies, these invariants 204b824378bSEnji Cooper * are impossible to test. 205b824378bSEnji Cooper */ 206b824378bSEnji Cooper ATF_REQUIRE(sbuf_len(sb) == 0); 207b824378bSEnji Cooper 208b824378bSEnji Cooper ATF_CHECK(sbuf_setpos(sb, -1) == -1); 209b824378bSEnji Cooper ATF_CHECK(sbuf_setpos(sb, 0) == 0); 210b824378bSEnji Cooper ATF_CHECK(sbuf_setpos(sb, 1) == -1); 211b824378bSEnji Cooper 212b824378bSEnji Cooper ATF_REQUIRE_MSG(sbuf_cat(sb, test_string) == 0, "sbuf_cat failed"); 213b824378bSEnji Cooper 214b824378bSEnji Cooper buf_len = sbuf_len(sb); 215b824378bSEnji Cooper test_string_len = strlen(test_string); 216b824378bSEnji Cooper test_string_chopped_len = test_string_len - TEST_STRING_CHOP_COUNT; 217b824378bSEnji Cooper ATF_REQUIRE_MSG(buf_len == (ssize_t)test_string_len, 218b824378bSEnji Cooper "sbuf length (%zd) != test_string length (%zu)", buf_len, 219b824378bSEnji Cooper test_string_len); 220b824378bSEnji Cooper 221b824378bSEnji Cooper /* Out of bounds (under length) */ 222b824378bSEnji Cooper ATF_CHECK(sbuf_setpos(sb, -1) == -1); 223b824378bSEnji Cooper /* 224b824378bSEnji Cooper * Out of bounds (over length) 225b824378bSEnji Cooper * 226b824378bSEnji Cooper * Note: SBUF_INCLUDENUL not set, so take '\0' into account. 227b824378bSEnji Cooper */ 228b824378bSEnji Cooper ATF_CHECK(sbuf_setpos(sb, test_string_len + 2) == -1); 229b824378bSEnji Cooper /* Within bounds */ 230b824378bSEnji Cooper ATF_CHECK(sbuf_setpos(sb, test_string_chopped_len) == 0); 231b824378bSEnji Cooper 232b824378bSEnji Cooper ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s", 233b824378bSEnji Cooper strerror(errno)); 234b824378bSEnji Cooper 235b824378bSEnji Cooper buf_len = sbuf_len(sb); 236b824378bSEnji Cooper ATF_REQUIRE_MSG(buf_len == (ssize_t)test_string_chopped_len, 237b824378bSEnji Cooper "sbuf_setpos didn't truncate string as expected"); 238b824378bSEnji Cooper ATF_REQUIRE_MSG(strncmp(sbuf_data(sb), test_string, buf_len) == 0, 239b824378bSEnji Cooper "sbuf (\"%s\") != test string (\"%s\") for [0,%zd]", sbuf_data(sb), 240b824378bSEnji Cooper test_string, buf_len); 241b824378bSEnji Cooper 242b824378bSEnji Cooper sbuf_delete(sb); 243b824378bSEnji Cooper } 244b824378bSEnji Cooper 245b824378bSEnji Cooper ATF_TP_ADD_TCS(tp) 246b824378bSEnji Cooper { 247b824378bSEnji Cooper ATF_TP_ADD_TC(tp, sbuf_clear_test); 248b824378bSEnji Cooper ATF_TP_ADD_TC(tp, sbuf_done_and_sbuf_finish_test); 2497d7db529SConrad Meyer ATF_TP_ADD_TC(tp, sbuf_drain_ret0_test); 250b824378bSEnji Cooper ATF_TP_ADD_TC(tp, sbuf_len_test); 2517d7db529SConrad Meyer ATF_TP_ADD_TC(tp, sbuf_new_fixedlen); 252b824378bSEnji Cooper #if 0 253b824378bSEnji Cooper /* TODO */ 254b824378bSEnji Cooper #ifdef HAVE_SBUF_CLEAR_FLAGS 255b824378bSEnji Cooper ATF_TP_ADD_TC(tp, sbuf_clear_flags_test); 256b824378bSEnji Cooper #endif 257b824378bSEnji Cooper #ifdef HAVE_SBUF_GET_FLAGS 258b824378bSEnji Cooper ATF_TP_ADD_TC(tp, sbuf_get_flags_test); 259b824378bSEnji Cooper #endif 260b824378bSEnji Cooper ATF_TP_ADD_TC(tp, sbuf_new_positive_test); 261b824378bSEnji Cooper ATF_TP_ADD_TC(tp, sbuf_new_negative_test); 262b824378bSEnji Cooper #ifdef HAVE_SBUF_SET_FLAGS 263b824378bSEnji Cooper ATF_TP_ADD_TC(tp, sbuf_set_flags_test); 264b824378bSEnji Cooper #endif 265b824378bSEnji Cooper #endif 266b824378bSEnji Cooper ATF_TP_ADD_TC(tp, sbuf_setpos_test); 267b824378bSEnji Cooper 268b824378bSEnji Cooper return (atf_no_error()); 269b824378bSEnji Cooper } 270