fmemopen2_test.c revision 290537
1246120Sgahr/*- 2246120SgahrCopyright (C) 2013 Pietro Cerutti <gahr@FreeBSD.org> 3246120Sgahr 4246120SgahrRedistribution and use in source and binary forms, with or without 5246120Sgahrmodification, are permitted provided that the following conditions 6246120Sgahrare met: 7246120Sgahr1. Redistributions of source code must retain the above copyright 8246120Sgahr notice, this list of conditions and the following disclaimer. 9246120Sgahr2. Redistributions in binary form must reproduce the above copyright 10246120Sgahr notice, this list of conditions and the following disclaimer in the 11246120Sgahr documentation and/or other materials provided with the distribution. 12246120Sgahr 13246120SgahrTHIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14246120SgahrANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15246120SgahrIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16246120SgahrARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17246120SgahrFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18246120SgahrDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19246120SgahrOR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20246120SgahrHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21246120SgahrLIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22246120SgahrOUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23246120SgahrSUCH DAMAGE. 24246120Sgahr*/ 25246120Sgahr 26246120Sgahr/* 27246120Sgahr * Test basic FILE * functions (fread, fwrite, fseek, fclose) against 28246120Sgahr * a FILE * retrieved using fmemopen() 29246120Sgahr */ 30246120Sgahr 31246120Sgahr#include <sys/cdefs.h> 32246120Sgahr__FBSDID("$FreeBSD: head/lib/libc/tests/stdio/fmemopen2_test.c 290537 2015-11-08 06:37:50Z ngie $"); 33246120Sgahr 34246120Sgahr#include <errno.h> 35246120Sgahr#include <stdio.h> 36246120Sgahr#include <string.h> 37246120Sgahr#include <strings.h> 38290537Sngie 39274592Sngie#include <atf-c.h> 40246120Sgahr 41274592SngieATF_TC_WITHOUT_HEAD(test_preexisting); 42274592SngieATF_TC_BODY(test_preexisting, tc) 43246120Sgahr{ 44290537Sngie /* Use a pre-existing buffer. */ 45246120Sgahr char buf[512]; 46246120Sgahr char buf2[512]; 47246120Sgahr char str[] = "Test writing some stuff"; 48246120Sgahr char str2[] = "AAAAAAAAA"; 49246120Sgahr char str3[] = "AAAA writing some stuff"; 50246120Sgahr FILE *fp; 51246120Sgahr size_t nofw, nofr; 52246120Sgahr int rc; 53246120Sgahr 54246148Sgahr /* Open a FILE * using fmemopen. */ 55246206Sgahr fp = fmemopen(buf, sizeof(buf), "w"); 56274592Sngie ATF_REQUIRE(fp != NULL); 57246120Sgahr 58246148Sgahr /* Write to the buffer. */ 59246206Sgahr nofw = fwrite(str, 1, sizeof(str), fp); 60274592Sngie ATF_REQUIRE(nofw == sizeof(str)); 61246120Sgahr 62246148Sgahr /* Close the FILE *. */ 63246206Sgahr rc = fclose(fp); 64274592Sngie ATF_REQUIRE(rc == 0); 65246120Sgahr 66246148Sgahr /* Re-open the FILE * to read back the data. */ 67246206Sgahr fp = fmemopen(buf, sizeof(buf), "r"); 68274592Sngie ATF_REQUIRE(fp != NULL); 69246120Sgahr 70246148Sgahr /* Read from the buffer. */ 71246206Sgahr bzero(buf2, sizeof(buf2)); 72246206Sgahr nofr = fread(buf2, 1, sizeof(buf2), fp); 73274592Sngie ATF_REQUIRE(nofr == sizeof(buf2)); 74246120Sgahr 75290537Sngie /* 76246148Sgahr * Since a write on a FILE * retrieved by fmemopen 77246120Sgahr * will add a '\0' (if there's space), we can check 78246148Sgahr * the strings for equality. 79246148Sgahr */ 80274592Sngie ATF_REQUIRE(strcmp(str, buf2) == 0); 81246120Sgahr 82246148Sgahr /* Close the FILE *. */ 83246206Sgahr rc = fclose(fp); 84274592Sngie ATF_REQUIRE(rc == 0); 85246120Sgahr 86246148Sgahr /* Now open a FILE * on the first 4 bytes of the string. */ 87246206Sgahr fp = fmemopen(str, 4, "w"); 88274592Sngie ATF_REQUIRE(fp != NULL); 89246120Sgahr 90246148Sgahr /* 91246148Sgahr * Try to write more bytes than we shoud, we'll get a short count (4). 92246148Sgahr */ 93246206Sgahr nofw = fwrite(str2, 1, sizeof(str2), fp); 94274592Sngie ATF_REQUIRE(nofw == 4); 95246120Sgahr 96246148Sgahr /* Close the FILE *. */ 97246206Sgahr rc = fclose(fp); 98288382Sdelphij ATF_REQUIRE(rc == 0); 99246120Sgahr 100246148Sgahr /* Check that the string was not modified after the first 4 bytes. */ 101274592Sngie ATF_REQUIRE(strcmp(str, str3) == 0); 102246120Sgahr} 103246120Sgahr 104274592SngieATF_TC_WITHOUT_HEAD(test_autoalloc); 105274592SngieATF_TC_BODY(test_autoalloc, tc) 106246120Sgahr{ 107290537Sngie /* Let fmemopen allocate the buffer. */ 108246120Sgahr char str[] = "A quick test"; 109246120Sgahr FILE *fp; 110246120Sgahr long pos; 111246120Sgahr size_t nofw, nofr, i; 112246120Sgahr int rc; 113246120Sgahr 114246148Sgahr /* Open a FILE * using fmemopen. */ 115246206Sgahr fp = fmemopen(NULL, 512, "w+"); 116274592Sngie ATF_REQUIRE(fp != NULL); 117246120Sgahr 118246120Sgahr /* fill the buffer */ 119246120Sgahr for (i = 0; i < 512; i++) { 120246206Sgahr nofw = fwrite("a", 1, 1, fp); 121274592Sngie ATF_REQUIRE(nofw == 1); 122246120Sgahr } 123246120Sgahr 124246148Sgahr /* Get the current position into the stream. */ 125246206Sgahr pos = ftell(fp); 126274592Sngie ATF_REQUIRE(pos == 512); 127246120Sgahr 128290537Sngie /* Try to write past the end, we should get a short object count (0) */ 129246206Sgahr nofw = fwrite("a", 1, 1, fp); 130274592Sngie ATF_REQUIRE(nofw == 0); 131246120Sgahr 132246148Sgahr /* Close the FILE *. */ 133246206Sgahr rc = fclose(fp); 134274592Sngie ATF_REQUIRE(rc == 0); 135266971Sgahr 136266971Sgahr /* Open a FILE * using a wrong mode */ 137266971Sgahr fp = fmemopen(NULL, 512, "r"); 138274592Sngie ATF_REQUIRE(fp == NULL); 139266971Sgahr 140266971Sgahr fp = fmemopen(NULL, 512, "w"); 141274592Sngie ATF_REQUIRE(fp == NULL); 142246120Sgahr} 143246120Sgahr 144274592SngieATF_TC_WITHOUT_HEAD(test_data_length); 145274592SngieATF_TC_BODY(test_data_length, tc) 146246148Sgahr{ 147246148Sgahr /* 148246148Sgahr * Here we test that a read operation doesn't go past the end of the 149246148Sgahr * data actually written, and that a SEEK_END seeks from the end of the 150246148Sgahr * data, not of the whole buffer. 151246148Sgahr */ 152246148Sgahr FILE *fp; 153246148Sgahr char buf[512] = {'\0'}; 154246148Sgahr char str[] = "Test data length. "; 155246148Sgahr char str2[] = "Do we have two sentences?"; 156246148Sgahr char str3[sizeof(str) + sizeof(str2) -1]; 157246148Sgahr long pos; 158246148Sgahr size_t nofw, nofr; 159246148Sgahr int rc; 160246148Sgahr 161246148Sgahr /* Open a FILE * for updating our buffer. */ 162246206Sgahr fp = fmemopen(buf, sizeof(buf), "w+"); 163274592Sngie ATF_REQUIRE(fp != NULL); 164246148Sgahr 165246148Sgahr /* Write our string into the buffer. */ 166246206Sgahr nofw = fwrite(str, 1, sizeof(str), fp); 167274592Sngie ATF_REQUIRE(nofw == sizeof(str)); 168246148Sgahr 169290537Sngie /* Now seek to the end and check that ftell gives us sizeof(str). */ 170246206Sgahr rc = fseek(fp, 0, SEEK_END); 171274592Sngie ATF_REQUIRE(rc == 0); 172246206Sgahr pos = ftell(fp); 173274592Sngie ATF_REQUIRE(pos == sizeof(str)); 174246148Sgahr 175246148Sgahr /* Close the FILE *. */ 176246206Sgahr rc = fclose(fp); 177274592Sngie ATF_REQUIRE(rc == 0); 178246148Sgahr 179246148Sgahr /* Reopen the buffer for appending. */ 180246206Sgahr fp = fmemopen(buf, sizeof(buf), "a+"); 181274592Sngie ATF_REQUIRE(fp != NULL); 182246148Sgahr 183246148Sgahr /* We should now be writing after the first string. */ 184246206Sgahr nofw = fwrite(str2, 1, sizeof(str2), fp); 185274592Sngie ATF_REQUIRE(nofw == sizeof(str2)); 186246148Sgahr 187246148Sgahr /* Rewind the FILE *. */ 188246206Sgahr rc = fseek(fp, 0, SEEK_SET); 189274592Sngie ATF_REQUIRE(rc == 0); 190246148Sgahr 191246148Sgahr /* Make sure we're at the beginning. */ 192246206Sgahr pos = ftell(fp); 193274592Sngie ATF_REQUIRE(pos == 0); 194246148Sgahr 195246148Sgahr /* Read the whole buffer. */ 196246206Sgahr nofr = fread(str3, 1, sizeof(buf), fp); 197274592Sngie ATF_REQUIRE(nofr == sizeof(str3)); 198246148Sgahr 199246148Sgahr /* Make sure the two strings are there. */ 200274592Sngie ATF_REQUIRE(strncmp(str3, str, sizeof(str) - 1) == 0); 201274592Sngie ATF_REQUIRE(strncmp(str3 + sizeof(str) - 1, str2, sizeof(str2)) == 0); 202246148Sgahr 203246148Sgahr /* Close the FILE *. */ 204246206Sgahr rc = fclose(fp); 205274592Sngie ATF_REQUIRE(rc == 0); 206246148Sgahr} 207246148Sgahr 208274592SngieATF_TC_WITHOUT_HEAD(test_binary); 209274592SngieATF_TC_BODY(test_binary, tc) 210246148Sgahr{ 211246148Sgahr /* 212246148Sgahr * Make sure that NULL bytes are never appended when opening a buffer 213246148Sgahr * in binary mode. 214246148Sgahr */ 215246148Sgahr 216246148Sgahr FILE *fp; 217246148Sgahr char buf[20]; 218246148Sgahr char str[] = "Test"; 219246148Sgahr size_t nofw; 220246148Sgahr int rc, i; 221246148Sgahr 222246148Sgahr /* Pre-fill the buffer. */ 223246206Sgahr memset(buf, 'A', sizeof(buf)); 224246148Sgahr 225246148Sgahr /* Open a FILE * in binary mode. */ 226246206Sgahr fp = fmemopen(buf, sizeof(buf), "w+b"); 227274592Sngie ATF_REQUIRE(fp != NULL); 228246148Sgahr 229246148Sgahr /* Write some data into it. */ 230246206Sgahr nofw = fwrite(str, 1, strlen(str), fp); 231274592Sngie ATF_REQUIRE(nofw == strlen(str)); 232246148Sgahr 233246148Sgahr /* Make sure that the buffer doesn't contain any NULL bytes. */ 234246148Sgahr for (i = 0; i < sizeof(buf); i++) 235274592Sngie ATF_REQUIRE(buf[i] != '\0'); 236246148Sgahr 237246148Sgahr /* Close the FILE *. */ 238246206Sgahr rc = fclose(fp); 239274592Sngie ATF_REQUIRE(rc == 0); 240246148Sgahr} 241246148Sgahr 242274592SngieATF_TC_WITHOUT_HEAD(test_append_binary_pos); 243274592SngieATF_TC_BODY(test_append_binary_pos, tc) 244266971Sgahr{ 245266971Sgahr /* 246266971Sgahr * For compatibility with other implementations (glibc), we set the 247266971Sgahr * position to 0 when opening an automatically allocated binary stream 248266971Sgahr * for appending. 249266971Sgahr */ 250266971Sgahr 251266971Sgahr FILE *fp; 252266971Sgahr 253266971Sgahr fp = fmemopen(NULL, 16, "ab+"); 254274592Sngie ATF_REQUIRE(ftell(fp) == 0L); 255266971Sgahr fclose(fp); 256266971Sgahr 257290537Sngie /* Make sure that a pre-allocated buffer behaves correctly. */ 258266971Sgahr char buf[] = "Hello"; 259266971Sgahr fp = fmemopen(buf, sizeof(buf), "ab+"); 260274592Sngie ATF_REQUIRE(ftell(fp) == strlen(buf)); 261266971Sgahr fclose(fp); 262266971Sgahr} 263266971Sgahr 264274592SngieATF_TC_WITHOUT_HEAD(test_size_0); 265274592SngieATF_TC_BODY(test_size_0, tc) 266266971Sgahr{ 267290537Sngie /* POSIX mandates that we return EINVAL if size is 0. */ 268266971Sgahr 269266971Sgahr FILE *fp; 270266971Sgahr 271266971Sgahr fp = fmemopen(NULL, 0, "r+"); 272274592Sngie ATF_REQUIRE(fp == NULL); 273274592Sngie ATF_REQUIRE(errno == EINVAL); 274266971Sgahr} 275266971Sgahr 276274592SngieATF_TP_ADD_TCS(tp) 277246120Sgahr{ 278274592Sngie 279274592Sngie ATF_TP_ADD_TC(tp, test_autoalloc); 280274592Sngie ATF_TP_ADD_TC(tp, test_preexisting); 281274592Sngie ATF_TP_ADD_TC(tp, test_data_length); 282274592Sngie ATF_TP_ADD_TC(tp, test_binary); 283274592Sngie ATF_TP_ADD_TC(tp, test_append_binary_pos); 284274592Sngie ATF_TP_ADD_TC(tp, test_size_0); 285274592Sngie 286274592Sngie return (atf_no_error()); 287246120Sgahr} 288